diff --git a/DOCS.md b/DOCS.md index f9695ed..f3dbad5 100644 --- a/DOCS.md +++ b/DOCS.md @@ -3,8 +3,6 @@
LPF2EventEmitter
-
LPF2HubHub
-
WeDo2HubHub
@@ -60,289 +58,7 @@ Emits when a LPF2 Hub device is found. | Param | Type | | --- | --- | -| hub | [WeDo2Hub](#WeDo2Hub) \| [LPF2Hub](#LPF2Hub) | - - - -## LPF2Hub ⇐ Hub -**Kind**: global class -**Extends**: Hub - -* [LPF2Hub](#LPF2Hub) ⇐ Hub - * [new LPF2Hub()](#new_LPF2Hub_new) - * [.name](#Hub+name) - * [.uuid](#Hub+uuid) - * [.rssi](#Hub+rssi) - * [.batteryLevel](#Hub+batteryLevel) - * [.current](#Hub+current) - * [.setLEDColor(color)](#LPF2Hub+setLEDColor) ⇒ Promise - * [.setMotorSpeed(port, speed, [time])](#LPF2Hub+setMotorSpeed) ⇒ Promise - * [.setMotorAngle(port, angle, [speed])](#LPF2Hub+setMotorAngle) ⇒ Promise - * [.connect()](#Hub+connect) ⇒ Promise - * [.disconnect()](#Hub+disconnect) ⇒ Promise - * [.subscribe(port, [mode])](#Hub+subscribe) ⇒ Promise - * [.unsubscribe(port)](#Hub+unsubscribe) ⇒ Promise - * [.sleep(delay)](#Hub+sleep) ⇒ Promise - * [.wait(commands)](#Hub+wait) ⇒ Promise - * ["button" (button, state)](#LPF2Hub+event_button) - * ["distance" (port, distance)](#LPF2Hub+event_distance) - * ["color" (port, color)](#LPF2Hub+event_color) - * ["tilt" (port, x, y)](#LPF2Hub+event_tilt) - * ["rotate" (port, rotation)](#LPF2Hub+event_rotate) - * ["attach" (port, type)](#Hub+event_attach) - * ["detach" (port)](#Hub+event_detach) - - - -### new LPF2Hub() -The LPF2Hub is emitted if the discovered device is either a Boost Move Hub, Powered Up Hub, or Powered Up Remote. - - - -### lpF2Hub.name -**Kind**: instance property of [LPF2Hub](#LPF2Hub) -**Read only**: true -**Properties** - -| Name | Type | Description | -| --- | --- | --- | -| name | string | Name of the hub | - - - -### lpF2Hub.uuid -**Kind**: instance property of [LPF2Hub](#LPF2Hub) -**Read only**: true -**Properties** - -| Name | Type | Description | -| --- | --- | --- | -| uuid | string | UUID of the hub | - - - -### lpF2Hub.rssi -**Kind**: instance property of [LPF2Hub](#LPF2Hub) -**Read only**: true -**Properties** - -| Name | Type | Description | -| --- | --- | --- | -| rssi | number | Signal strength of the hub | - - - -### lpF2Hub.batteryLevel -**Kind**: instance property of [LPF2Hub](#LPF2Hub) -**Read only**: true -**Properties** - -| Name | Type | Description | -| --- | --- | --- | -| batteryLevel | number | Battery level of the hub (Percentage between 0-100) | - - - -### lpF2Hub.current -**Kind**: instance property of [LPF2Hub](#LPF2Hub) -**Read only**: true -**Properties** - -| Name | Type | Description | -| --- | --- | --- | -| current | number | Current usage of the hub (Amps) | - - - -### lpF2Hub.setLEDColor(color) ⇒ Promise -Set the color of the LED on the Hub via a color value. - -**Kind**: instance method of [LPF2Hub](#LPF2Hub) -**Returns**: Promise - Resolved upon successful issuance of command. - -| Param | Type | Description | -| --- | --- | --- | -| color | number | A number representing one of the LED color consts. | - - - -### lpF2Hub.setMotorSpeed(port, speed, [time]) ⇒ Promise -Set the motor speed on a given port. - -**Kind**: instance method of [LPF2Hub](#LPF2Hub) -**Returns**: Promise - Resolved upon successful completion of command. If time is specified, this is once the motor is finished. - -| Param | Type | Description | -| --- | --- | --- | -| port | string | | -| speed | number | For forward, a value between 1 - 100 should be set. For reverse, a value between -1 to -100. Stop is 0. | -| [time] | number | How long to activate the motor for (in milliseconds). Leave empty to turn the motor on indefinitely. | - - - -### lpF2Hub.setMotorAngle(port, angle, [speed]) ⇒ Promise -Rotate a motor by a given angle. - -**Kind**: instance method of [LPF2Hub](#LPF2Hub) -**Returns**: Promise - Resolved upon successful completion of command (ie. once the motor is finished). - -| Param | Type | Default | Description | -| --- | --- | --- | --- | -| port | string | | | -| angle | number | | How much the motor should be rotated (in degrees). | -| [speed] | number | 100 | How fast the motor should be rotated. | - - - -### lpF2Hub.connect() ⇒ Promise -Connect to the Hub. - -**Kind**: instance method of [LPF2Hub](#LPF2Hub) -**Overrides**: [connect](#Hub+connect) -**Returns**: Promise - Resolved upon successful connect. - - -### lpF2Hub.disconnect() ⇒ Promise -Disconnect the Hub. - -**Kind**: instance method of [LPF2Hub](#LPF2Hub) -**Returns**: Promise - Resolved upon successful disconnect. - - -### lpF2Hub.subscribe(port, [mode]) ⇒ Promise -Subscribe to sensor notifications on a given port. - -**Kind**: instance method of [LPF2Hub](#LPF2Hub) -**Returns**: Promise - Resolved upon successful issuance of command. - -| Param | Type | Description | -| --- | --- | --- | -| port | string | | -| [mode] | number | The sensor mode to activate. If no mode is provided, the default for that sensor will be chosen. | - - - -### lpF2Hub.unsubscribe(port) ⇒ Promise -Unsubscribe to sensor notifications on a given port. - -**Kind**: instance method of [LPF2Hub](#LPF2Hub) -**Returns**: Promise - Resolved upon successful issuance of command. - -| Param | Type | -| --- | --- | -| port | string | - - - -### lpF2Hub.sleep(delay) ⇒ Promise -Sleep a given amount of time. - -This is a helper method to make it easier to add delays into a chain of commands. - -**Kind**: instance method of [LPF2Hub](#LPF2Hub) -**Returns**: Promise - Resolved after the delay is finished. - -| Param | Type | Description | -| --- | --- | --- | -| delay | number | How long to sleep (in milliseconds). | - - - -### lpF2Hub.wait(commands) ⇒ Promise -Wait until a given list of concurrently running commands are complete. - -This is a helper method to make it easier to wait for concurrent commands to complete. - -**Kind**: instance method of [LPF2Hub](#LPF2Hub) -**Returns**: Promise - Resolved after the commands are finished. - -| Param | Type | Description | -| --- | --- | --- | -| commands | Array.<Promise.<any>> | Array of executing commands. | - - - -### "button" (button, state) -Emits when a button is pressed. - -**Kind**: event emitted by [LPF2Hub](#LPF2Hub) - -| Param | Type | Description | -| --- | --- | --- | -| button | string | | -| state | number | A number representing one of the button state consts. | - - - -### "distance" (port, distance) -Emits when a distance sensor is activated. - -**Kind**: event emitted by [LPF2Hub](#LPF2Hub) - -| Param | Type | Description | -| --- | --- | --- | -| port | string | | -| distance | number | Distance, in millimeters. | - - - -### "color" (port, color) -Emits when a color sensor is activated. - -**Kind**: event emitted by [LPF2Hub](#LPF2Hub) - -| Param | Type | Description | -| --- | --- | --- | -| port | string | | -| color | number | A number representing one of the LED color consts. | - - - -### "tilt" (port, x, y) -Emits when a tilt sensor is activated. - -**Kind**: event emitted by [LPF2Hub](#LPF2Hub) - -| Param | Type | Description | -| --- | --- | --- | -| port | string | If the event is fired from the Move Hub's in-built tilt sensor, the special port "TILT" is used. | -| x | number | | -| y | number | | - - - -### "rotate" (port, rotation) -Emits when a rotation sensor is activated. - -**Kind**: event emitted by [LPF2Hub](#LPF2Hub) - -| Param | Type | -| --- | --- | -| port | string | -| rotation | number | - - - -### "attach" (port, type) -Emits when a motor or sensor is attached to the Hub. - -**Kind**: event emitted by [LPF2Hub](#LPF2Hub) - -| Param | Type | Description | -| --- | --- | --- | -| port | string | | -| type | number | A number representing one of the peripheral consts. | - - - -### "detach" (port) -Emits when an attached motor or sensor is detached from the Hub. - -**Kind**: event emitted by [LPF2Hub](#LPF2Hub) - -| Param | Type | -| --- | --- | -| port | string | +| hub | [WeDo2Hub](#WeDo2Hub) \| LPF2Hub | diff --git a/README.md b/README.md index e8f7d42..a61fa75 100644 --- a/README.md +++ b/README.md @@ -53,8 +53,6 @@ Thanks go to Jorge Pereira ([@JorgePe](https://github.com/JorgePe)), Sebastian R
LPF2EventEmitter
-
LPF2HubHub
-
WeDo2HubHub
@@ -110,289 +108,7 @@ Emits when a LPF2 Hub device is found. | Param | Type | | --- | --- | -| hub | [WeDo2Hub](#WeDo2Hub) \| [LPF2Hub](#LPF2Hub) | - - - -## LPF2Hub ⇐ Hub -**Kind**: global class -**Extends**: Hub - -* [LPF2Hub](#LPF2Hub) ⇐ Hub - * [new LPF2Hub()](#new_LPF2Hub_new) - * [.name](#Hub+name) - * [.uuid](#Hub+uuid) - * [.rssi](#Hub+rssi) - * [.batteryLevel](#Hub+batteryLevel) - * [.current](#Hub+current) - * [.setLEDColor(color)](#LPF2Hub+setLEDColor) ⇒ Promise - * [.setMotorSpeed(port, speed, [time])](#LPF2Hub+setMotorSpeed) ⇒ Promise - * [.setMotorAngle(port, angle, [speed])](#LPF2Hub+setMotorAngle) ⇒ Promise - * [.connect()](#Hub+connect) ⇒ Promise - * [.disconnect()](#Hub+disconnect) ⇒ Promise - * [.subscribe(port, [mode])](#Hub+subscribe) ⇒ Promise - * [.unsubscribe(port)](#Hub+unsubscribe) ⇒ Promise - * [.sleep(delay)](#Hub+sleep) ⇒ Promise - * [.wait(commands)](#Hub+wait) ⇒ Promise - * ["button" (button, state)](#LPF2Hub+event_button) - * ["distance" (port, distance)](#LPF2Hub+event_distance) - * ["color" (port, color)](#LPF2Hub+event_color) - * ["tilt" (port, x, y)](#LPF2Hub+event_tilt) - * ["rotate" (port, rotation)](#LPF2Hub+event_rotate) - * ["attach" (port, type)](#Hub+event_attach) - * ["detach" (port)](#Hub+event_detach) - - - -### new LPF2Hub() -The LPF2Hub is emitted if the discovered device is either a Boost Move Hub, Powered Up Hub, or Powered Up Remote. - - - -### lpF2Hub.name -**Kind**: instance property of [LPF2Hub](#LPF2Hub) -**Read only**: true -**Properties** - -| Name | Type | Description | -| --- | --- | --- | -| name | string | Name of the hub | - - - -### lpF2Hub.uuid -**Kind**: instance property of [LPF2Hub](#LPF2Hub) -**Read only**: true -**Properties** - -| Name | Type | Description | -| --- | --- | --- | -| uuid | string | UUID of the hub | - - - -### lpF2Hub.rssi -**Kind**: instance property of [LPF2Hub](#LPF2Hub) -**Read only**: true -**Properties** - -| Name | Type | Description | -| --- | --- | --- | -| rssi | number | Signal strength of the hub | - - - -### lpF2Hub.batteryLevel -**Kind**: instance property of [LPF2Hub](#LPF2Hub) -**Read only**: true -**Properties** - -| Name | Type | Description | -| --- | --- | --- | -| batteryLevel | number | Battery level of the hub (Percentage between 0-100) | - - - -### lpF2Hub.current -**Kind**: instance property of [LPF2Hub](#LPF2Hub) -**Read only**: true -**Properties** - -| Name | Type | Description | -| --- | --- | --- | -| current | number | Current usage of the hub (Amps) | - - - -### lpF2Hub.setLEDColor(color) ⇒ Promise -Set the color of the LED on the Hub via a color value. - -**Kind**: instance method of [LPF2Hub](#LPF2Hub) -**Returns**: Promise - Resolved upon successful issuance of command. - -| Param | Type | Description | -| --- | --- | --- | -| color | number | A number representing one of the LED color consts. | - - - -### lpF2Hub.setMotorSpeed(port, speed, [time]) ⇒ Promise -Set the motor speed on a given port. - -**Kind**: instance method of [LPF2Hub](#LPF2Hub) -**Returns**: Promise - Resolved upon successful completion of command. If time is specified, this is once the motor is finished. - -| Param | Type | Description | -| --- | --- | --- | -| port | string | | -| speed | number | For forward, a value between 1 - 100 should be set. For reverse, a value between -1 to -100. Stop is 0. | -| [time] | number | How long to activate the motor for (in milliseconds). Leave empty to turn the motor on indefinitely. | - - - -### lpF2Hub.setMotorAngle(port, angle, [speed]) ⇒ Promise -Rotate a motor by a given angle. - -**Kind**: instance method of [LPF2Hub](#LPF2Hub) -**Returns**: Promise - Resolved upon successful completion of command (ie. once the motor is finished). - -| Param | Type | Default | Description | -| --- | --- | --- | --- | -| port | string | | | -| angle | number | | How much the motor should be rotated (in degrees). | -| [speed] | number | 100 | How fast the motor should be rotated. | - - - -### lpF2Hub.connect() ⇒ Promise -Connect to the Hub. - -**Kind**: instance method of [LPF2Hub](#LPF2Hub) -**Overrides**: [connect](#Hub+connect) -**Returns**: Promise - Resolved upon successful connect. - - -### lpF2Hub.disconnect() ⇒ Promise -Disconnect the Hub. - -**Kind**: instance method of [LPF2Hub](#LPF2Hub) -**Returns**: Promise - Resolved upon successful disconnect. - - -### lpF2Hub.subscribe(port, [mode]) ⇒ Promise -Subscribe to sensor notifications on a given port. - -**Kind**: instance method of [LPF2Hub](#LPF2Hub) -**Returns**: Promise - Resolved upon successful issuance of command. - -| Param | Type | Description | -| --- | --- | --- | -| port | string | | -| [mode] | number | The sensor mode to activate. If no mode is provided, the default for that sensor will be chosen. | - - - -### lpF2Hub.unsubscribe(port) ⇒ Promise -Unsubscribe to sensor notifications on a given port. - -**Kind**: instance method of [LPF2Hub](#LPF2Hub) -**Returns**: Promise - Resolved upon successful issuance of command. - -| Param | Type | -| --- | --- | -| port | string | - - - -### lpF2Hub.sleep(delay) ⇒ Promise -Sleep a given amount of time. - -This is a helper method to make it easier to add delays into a chain of commands. - -**Kind**: instance method of [LPF2Hub](#LPF2Hub) -**Returns**: Promise - Resolved after the delay is finished. - -| Param | Type | Description | -| --- | --- | --- | -| delay | number | How long to sleep (in milliseconds). | - - - -### lpF2Hub.wait(commands) ⇒ Promise -Wait until a given list of concurrently running commands are complete. - -This is a helper method to make it easier to wait for concurrent commands to complete. - -**Kind**: instance method of [LPF2Hub](#LPF2Hub) -**Returns**: Promise - Resolved after the commands are finished. - -| Param | Type | Description | -| --- | --- | --- | -| commands | Array.<Promise.<any>> | Array of executing commands. | - - - -### "button" (button, state) -Emits when a button is pressed. - -**Kind**: event emitted by [LPF2Hub](#LPF2Hub) - -| Param | Type | Description | -| --- | --- | --- | -| button | string | | -| state | number | A number representing one of the button state consts. | - - - -### "distance" (port, distance) -Emits when a distance sensor is activated. - -**Kind**: event emitted by [LPF2Hub](#LPF2Hub) - -| Param | Type | Description | -| --- | --- | --- | -| port | string | | -| distance | number | Distance, in millimeters. | - - - -### "color" (port, color) -Emits when a color sensor is activated. - -**Kind**: event emitted by [LPF2Hub](#LPF2Hub) - -| Param | Type | Description | -| --- | --- | --- | -| port | string | | -| color | number | A number representing one of the LED color consts. | - - - -### "tilt" (port, x, y) -Emits when a tilt sensor is activated. - -**Kind**: event emitted by [LPF2Hub](#LPF2Hub) - -| Param | Type | Description | -| --- | --- | --- | -| port | string | If the event is fired from the Move Hub's in-built tilt sensor, the special port "TILT" is used. | -| x | number | | -| y | number | | - - - -### "rotate" (port, rotation) -Emits when a rotation sensor is activated. - -**Kind**: event emitted by [LPF2Hub](#LPF2Hub) - -| Param | Type | -| --- | --- | -| port | string | -| rotation | number | - - - -### "attach" (port, type) -Emits when a motor or sensor is attached to the Hub. - -**Kind**: event emitted by [LPF2Hub](#LPF2Hub) - -| Param | Type | Description | -| --- | --- | --- | -| port | string | | -| type | number | A number representing one of the peripheral consts. | - - - -### "detach" (port) -Emits when an attached motor or sensor is detached from the Hub. - -**Kind**: event emitted by [LPF2Hub](#LPF2Hub) - -| Param | Type | -| --- | --- | -| port | string | +| hub | [WeDo2Hub](#WeDo2Hub) \| LPF2Hub | diff --git a/boostmovehub.ts b/boostmovehub.ts new file mode 100644 index 0000000..7612348 --- /dev/null +++ b/boostmovehub.ts @@ -0,0 +1,129 @@ +import { Peripheral } from "noble"; + +import { LPF2Hub } from "./lpf2hub"; +import { Port } from "./port"; + +import * as Consts from "./consts"; + +import Debug = require("debug"); +const debug = Debug("lpf2hub"); + + +/** + * The BoostMoveHub is emitted if the discovered device is a Boost Move Hub. + * @class BoostMoveHub + * @extends LPF2Hub + */ +export class BoostMoveHub extends LPF2Hub { + + + public static IsBoostMoveHub (peripheral: Peripheral) { + return (peripheral.advertisement.serviceUuids.indexOf(Consts.BLEServices.BOOST_MOVE_HUB) >= 0 && peripheral.advertisement.manufacturerData[3] === Consts.BLEManufacturerData.BOOST_MOVE_HUB_ID); + } + + + constructor (peripheral: Peripheral, autoSubscribe: boolean = true) { + super(peripheral, autoSubscribe); + this.type = Consts.Hubs.BOOST_MOVE_HUB; + this._ports = { + "A": new Port("A", 55), + "B": new Port("B", 56), + "AB": new Port("AB", 57), + "TILT": new Port("TILT", 58), + "C": new Port("C", 1), + "D": new Port("D", 2) + }; + debug("Discovered Boost Move Hub"); + } + + + public connect () { + return new Promise(async (resolve, reject) => { + debug("Connecting to Boost Move Hub"); + await super.connect(); + debug("Connect completed"); + return resolve(); + }); + } + + + /** + * Set the color of the LED on the Hub via a color value. + * @method BoostMoveHub#setLEDColor + * @param {number} color A number representing one of the LED color consts. + * @returns {Promise} Resolved upon successful issuance of command. + */ + public setLEDColor (color: number | boolean) { + return new Promise((resolve, reject) => { + if (color === false) { + color = 0; + } + const data = Buffer.from([0x08, 0x00, 0x81, 0x32, 0x11, 0x51, 0x00, color]); + this._writeMessage(Consts.BLECharacteristics.BOOST_ALL, data); + return resolve(); + }); + } + + + /** + * Set the motor speed on a given port. + * @method BoostMoveHub#setMotorSpeed + * @param {string} port + * @param {number} speed For forward, a value between 1 - 100 should be set. For reverse, a value between -1 to -100. Stop is 0. + * @param {number} [time] How long to activate the motor for (in milliseconds). Leave empty to turn the motor on indefinitely. + * @returns {Promise} Resolved upon successful completion of command. If time is specified, this is once the motor is finished. + */ + public setMotorSpeed (port: string, speed: number, time?: number) { + return new Promise((resolve, reject) => { + const portObj = this._ports[port]; + if (time) { + if (portObj.type === Consts.Devices.BOOST_INTERACTIVE_MOTOR || portObj.type === Consts.Devices.BOOST_MOVE_HUB_MOTOR) { + portObj.busy = true; + const data = Buffer.from([0x0c, 0x00, 0x81, portObj.value, 0x11, 0x09, 0x00, 0x00, this._mapSpeed(speed), 0x64, 0x7f, 0x03]); + data.writeUInt16LE(time > 65535 ? 65535 : time, 6); + this._writeMessage(Consts.BLECharacteristics.BOOST_ALL, data); + portObj.finished = () => { + return resolve(); + }; + } else { + const data = Buffer.from([0x08, 0x00, 0x81, portObj.value, 0x11, 0x51, 0x00, this._mapSpeed(speed)]); + this._writeMessage(Consts.BLECharacteristics.BOOST_ALL, data); + setTimeout(() => { + const data = Buffer.from([0x08, 0x00, 0x81, portObj.value, 0x11, 0x51, 0x00, 0x00]); + this._writeMessage(Consts.BLECharacteristics.BOOST_ALL, data); + return resolve(); + }, time); + } + } else { + const data = Buffer.from([0x08, 0x00, 0x81, portObj.value, 0x11, 0x51, 0x00, this._mapSpeed(speed)]); + this._writeMessage(Consts.BLECharacteristics.BOOST_ALL, data); + return resolve(); + } + }); + } + + + /** + * Rotate a motor by a given angle. + * @method BoostMoveHub#setMotorAngle + * @param {string} port + * @param {number} angle How much the motor should be rotated (in degrees). + * @param {number} [speed=100] How fast the motor should be rotated. + * @returns {Promise} Resolved upon successful completion of command (ie. once the motor is finished). + */ + public setMotorAngle (port: string, angle: number, speed: number = 100) { + const portObj = this._ports[port]; + return new Promise((resolve, reject) => { + portObj.busy = true; + const data = Buffer.from([0x0e, 0x00, 0x81, portObj.value, 0x11, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x7f, 0x03]); + data.writeUInt32LE(angle, 6); + data.writeUInt8(this._mapSpeed(speed), 10); + this._writeMessage(Consts.BLECharacteristics.BOOST_ALL, data); + portObj.finished = () => { + return resolve(); + }; + }); + } + + +} diff --git a/lpf2.ts b/lpf2.ts index 4790fb9..80e4f8f 100644 --- a/lpf2.ts +++ b/lpf2.ts @@ -1,7 +1,9 @@ import { Peripheral } from "noble"; +import { BoostMoveHub } from "./boostmovehub"; import { Hub } from "./hub"; -import { LPF2Hub } from "./lpf2hub"; +import { PUPHub } from "./puphub"; +import { PUPRemote } from "./pupremote"; import { WeDo2Hub } from "./wedo2hub"; import * as Consts from "./consts"; @@ -58,8 +60,12 @@ export class LPF2 extends EventEmitter { if (WeDo2Hub.IsWeDo2Hub(peripheral)) { hub = new WeDo2Hub(peripheral, this.autoSubscribe); - } else if (LPF2Hub.IsLPF2Hub(peripheral)) { - hub = new LPF2Hub(peripheral, this.autoSubscribe); + } else if (BoostMoveHub.IsBoostMoveHub(peripheral)) { + hub = new BoostMoveHub(peripheral, this.autoSubscribe); + } else if (PUPHub.IsPUPHub(peripheral)) { + hub = new PUPHub(peripheral, this.autoSubscribe); + } else if (PUPRemote.IsPUPRemote(peripheral)) { + hub = new PUPRemote(peripheral, this.autoSubscribe); } else { return; } @@ -135,4 +141,4 @@ export class LPF2 extends EventEmitter { } export default LPF2; -export { Hub, WeDo2Hub, LPF2Hub, Consts }; +export { Hub, WeDo2Hub, BoostMoveHub, PUPHub, PUPRemote, Consts }; diff --git a/lpf2hub.ts b/lpf2hub.ts index 5cd6f2d..b4be777 100644 --- a/lpf2hub.ts +++ b/lpf2hub.ts @@ -1,7 +1,7 @@ import { Peripheral } from "noble"; -import { Hub } from "./hub.js"; -import { Port } from "./port.js"; +import { Hub } from "./hub"; +import { Port } from "./port"; import * as Consts from "./consts"; @@ -10,184 +10,32 @@ const debug = Debug("lpf2hub"); /** - * The LPF2Hub is emitted if the discovered device is either a Boost Move Hub, Powered Up Hub, or Powered Up Remote. * @class LPF2Hub + * @ignore * @extends Hub */ export class LPF2Hub extends Hub { - public static IsLPF2Hub (peripheral: Peripheral) { - return (peripheral.advertisement.serviceUuids.indexOf(Consts.BLEServices.BOOST_MOVE_HUB) >= 0); - } - - private _lastTiltX: number = 0; private _lastTiltY: number = 0; private _messageBuffer: Buffer = Buffer.alloc(0); - constructor (peripheral: Peripheral, autoSubscribe: boolean = true) { - super(peripheral, autoSubscribe); - switch (peripheral.advertisement.manufacturerData[3]) { - case Consts.BLEManufacturerData.POWERED_UP_HUB_ID: - { - this.type = Consts.Hubs.POWERED_UP_HUB; - this._ports = { - "A": new Port("A", 0), - "B": new Port("B", 1), - "AB": new Port("AB", 57) - }; - debug("Discovered Powered Up Hub"); - break; - } - case Consts.BLEManufacturerData.POWERED_UP_REMOTE_ID: - { - this.type = Consts.Hubs.POWERED_UP_REMOTE; - this._ports = { - "LEFT": new Port("LEFT", 0), - "RIGHT": new Port("RIGHT", 1) - }; - debug("Discovered Powered Up Remote"); - break; - } - default: - { - this.type = Consts.Hubs.BOOST_MOVE_HUB; - this._ports = { - "A": new Port("A", 55), - "B": new Port("B", 56), - "AB": new Port("AB", 57), - "TILT": new Port("TILT", 58), - "C": new Port("C", 1), - "D": new Port("D", 2) - }; - debug("Discovered Boost Move Hub"); - break; - } - } - } - - public connect () { return new Promise(async (resolve, reject) => { - debug("Connecting to Hub"); await super.connect(); const characteristic = this._characteristics[Consts.BLECharacteristics.BOOST_ALL]; this._subscribeToCharacteristic(characteristic, this._parseMessage.bind(this)); this._writeMessage(Consts.BLECharacteristics.BOOST_ALL, Buffer.from([0x05, 0x00, 0x01, 0x02, 0x02])); // Activate button reports this._writeMessage(Consts.BLECharacteristics.BOOST_ALL, Buffer.from([0x0a, 0x00, 0x41, 0x3b, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01])); // Activate current reports this._writeMessage(Consts.BLECharacteristics.BOOST_ALL, Buffer.from([0x0a, 0x00, 0x41, 0x3c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01])); // Activate voltage reports - debug("Connect completed"); return resolve(); }); } - /** - * Set the color of the LED on the Hub via a color value. - * @method LPF2Hub#setLEDColor - * @param {number} color A number representing one of the LED color consts. - * @returns {Promise} Resolved upon successful issuance of command. - */ - public setLEDColor (color: number | boolean) { - return new Promise((resolve, reject) => { - if (color === false) { - color = 0; - } - let data = Buffer.from([0x08, 0x00, 0x81, 0x32, 0x11, 0x51, 0x00, color]); - if (this.type === Consts.Hubs.POWERED_UP_REMOTE) { - data = Buffer.from([0x08, 0x00, 0x81, 0x34, 0x11, 0x51, 0x00, color]); - } - this._writeMessage(Consts.BLECharacteristics.BOOST_ALL, data); - return resolve(); - }); - } - - - /** - * Set the motor speed on a given port. - * @method LPF2Hub#setMotorSpeed - * @param {string} port - * @param {number} speed For forward, a value between 1 - 100 should be set. For reverse, a value between -1 to -100. Stop is 0. - * @param {number} [time] How long to activate the motor for (in milliseconds). Leave empty to turn the motor on indefinitely. - * @returns {Promise} Resolved upon successful completion of command. If time is specified, this is once the motor is finished. - */ - public setMotorSpeed (port: string, speed: number, time?: number) { - if (this.type === Consts.Hubs.POWERED_UP_REMOTE) { - throw new Error("Motor commands are not available when using the Powered Up Remote"); - } - return new Promise((resolve, reject) => { - const portObj = this._ports[port]; - if (time) { - if (this.type === Consts.Hubs.BOOST_MOVE_HUB && (portObj.type === Consts.Devices.BOOST_INTERACTIVE_MOTOR || portObj.type === Consts.Devices.BOOST_MOVE_HUB_MOTOR)) { - portObj.busy = true; - const data = Buffer.from([0x0c, 0x00, 0x81, portObj.value, 0x11, 0x09, 0x00, 0x00, this._mapSpeed(speed), 0x64, 0x7f, 0x03]); - data.writeUInt16LE(time > 65535 ? 65535 : time, 6); - this._writeMessage(Consts.BLECharacteristics.BOOST_ALL, data); - portObj.finished = () => { - return resolve(); - }; - } else { - let data = Buffer.from([0x08, 0x00, 0x81, portObj.value, 0x11, 0x51, 0x00, this._mapSpeed(speed)]); - if (this.type === Consts.Hubs.POWERED_UP_HUB) { - data = Buffer.from([0x0a, 0x00, 0x81, portObj.value, 0x11, 0x60, 0x00, this._mapSpeed(speed), 0x00, 0x00]); - } - this._writeMessage(Consts.BLECharacteristics.BOOST_ALL, data); - setTimeout(() => { - let data = Buffer.from([0x08, 0x00, 0x81, portObj.value, 0x11, 0x51, 0x00, 0x00]); - if (this.type === Consts.Hubs.POWERED_UP_HUB) { - data = Buffer.from([0x0a, 0x00, 0x81, portObj.value, 0x11, 0x60, 0x00, 0x00, 0x00, 0x00]); - } - this._writeMessage(Consts.BLECharacteristics.BOOST_ALL, data); - return resolve(); - }, time); - } - } else { - let data = Buffer.from([0x08, 0x00, 0x81, portObj.value, 0x11, 0x51, 0x00, this._mapSpeed(speed)]); - if (this.type === Consts.Hubs.POWERED_UP_HUB) { - data = Buffer.from([0x0a, 0x00, 0x81, portObj.value, 0x11, 0x60, 0x00, this._mapSpeed(speed), 0x00, 0x00]); - } - this._writeMessage(Consts.BLECharacteristics.BOOST_ALL, data); - return resolve(); - } - }); - } - - - /** - * Rotate a motor by a given angle. - * @method LPF2Hub#setMotorAngle - * @param {string} port - * @param {number} angle How much the motor should be rotated (in degrees). - * @param {number} [speed=100] How fast the motor should be rotated. - * @returns {Promise} Resolved upon successful completion of command (ie. once the motor is finished). - */ - public setMotorAngle (port: string, angle: number, speed: number = 100) { - const portObj = this._ports[port]; - if (this.type === Consts.Hubs.POWERED_UP_REMOTE) { - throw new Error("Motor commands are not available when using the Powered Up Remote"); - } - if (this.type !== Consts.Hubs.BOOST_MOVE_HUB) { - throw new Error("Angle rotation is only available when using the Boost Move Hub"); - } - if (!(portObj.type === Consts.Devices.BOOST_INTERACTIVE_MOTOR || portObj.type === Consts.Devices.BOOST_MOVE_HUB_MOTOR)) { - throw new Error("Angle rotation is only available when using a Boost Interactive Motor or Boost Move Hub Motor"); - } - return new Promise((resolve, reject) => { - portObj.busy = true; - const data = Buffer.from([0x0e, 0x00, 0x81, portObj.value, 0x11, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x7f, 0x03]); - data.writeUInt32LE(angle, 6); - data.writeUInt8(this._mapSpeed(speed), 10); - this._writeMessage(Consts.BLECharacteristics.BOOST_ALL, data); - portObj.finished = () => { - return resolve(); - }; - }); - } - - protected _activatePortDevice (port: number, type: number, mode: number, format: number, callback?: () => void) { this._writeMessage(Consts.BLECharacteristics.BOOST_ALL, Buffer.from([0x0a, 0x00, 0x41, port, mode, 0x01, 0x00, 0x00, 0x00, 0x01]), callback); } @@ -198,7 +46,7 @@ export class LPF2Hub extends Hub { } - private _writeMessage (uuid: string, message: Buffer, callback?: () => void) { + protected _writeMessage (uuid: string, message: Buffer, callback?: () => void) { const characteristic = this._characteristics[uuid]; if (characteristic) { characteristic.write(message, false, callback); diff --git a/puphub.ts b/puphub.ts new file mode 100644 index 0000000..35c9545 --- /dev/null +++ b/puphub.ts @@ -0,0 +1,93 @@ +import { Peripheral } from "noble"; + +import { LPF2Hub } from "./lpf2hub"; +import { Port } from "./port"; + +import * as Consts from "./consts"; + +import Debug = require("debug"); +const debug = Debug("lpf2hub"); + + +/** + * The PUPHub is emitted if the discovered device is a Powered Up Hub. + * @class PUPHub + * @extends LPF2Hub + */ +export class PUPHub extends LPF2Hub { + + + public static IsPUPHub (peripheral: Peripheral) { + return (peripheral.advertisement.serviceUuids.indexOf(Consts.BLEServices.BOOST_MOVE_HUB) >= 0 && peripheral.advertisement.manufacturerData[3] === Consts.BLEManufacturerData.POWERED_UP_HUB_ID); + } + + + constructor (peripheral: Peripheral, autoSubscribe: boolean = true) { + super(peripheral, autoSubscribe); + this.type = Consts.Hubs.POWERED_UP_HUB; + this._ports = { + "A": new Port("A", 0), + "B": new Port("B", 1), + "AB": new Port("AB", 57) + }; + debug("Discovered Powered Up Hub"); + } + + + public connect () { + return new Promise(async (resolve, reject) => { + debug("Connecting to Powered Up Hub"); + await super.connect(); + debug("Connect completed"); + return resolve(); + }); + } + + + /** + * Set the color of the LED on the Hub via a color value. + * @method PUPHub#setLEDColor + * @param {number} color A number representing one of the LED color consts. + * @returns {Promise} Resolved upon successful issuance of command. + */ + public setLEDColor (color: number | boolean) { + return new Promise((resolve, reject) => { + if (color === false) { + color = 0; + } + const data = Buffer.from([0x08, 0x00, 0x81, 0x32, 0x11, 0x51, 0x00, color]); + this._writeMessage(Consts.BLECharacteristics.BOOST_ALL, data); + return resolve(); + }); + } + + + /** + * Set the motor speed on a given port. + * @method PUPHub#setMotorSpeed + * @param {string} port + * @param {number} speed For forward, a value between 1 - 100 should be set. For reverse, a value between -1 to -100. Stop is 0. + * @param {number} [time] How long to activate the motor for (in milliseconds). Leave empty to turn the motor on indefinitely. + * @returns {Promise} Resolved upon successful completion of command. If time is specified, this is once the motor is finished. + */ + public setMotorSpeed (port: string, speed: number, time?: number) { + return new Promise((resolve, reject) => { + const portObj = this._ports[port]; + if (time) { + const data = Buffer.from([0x0a, 0x00, 0x81, portObj.value, 0x11, 0x60, 0x00, this._mapSpeed(speed), 0x00, 0x00]); + this._writeMessage(Consts.BLECharacteristics.BOOST_ALL, data); + setTimeout(() => { + const data = Buffer.from([0x0a, 0x00, 0x81, portObj.value, 0x11, 0x60, 0x00, 0x00, 0x00, 0x00]); + this._writeMessage(Consts.BLECharacteristics.BOOST_ALL, data); + return resolve(); + }, time); + } else { + const data = Buffer.from([0x0a, 0x00, 0x81, portObj.value, 0x11, 0x60, 0x00, this._mapSpeed(speed), 0x00, 0x00]); + this._writeMessage(Consts.BLECharacteristics.BOOST_ALL, data); + return resolve(); + } + }); + } + + +} diff --git a/pupremote.ts b/pupremote.ts new file mode 100644 index 0000000..eb7f6e8 --- /dev/null +++ b/pupremote.ts @@ -0,0 +1,64 @@ +import { Peripheral } from "noble"; + +import { LPF2Hub } from "./lpf2hub"; +import { Port } from "./port"; + +import * as Consts from "./consts"; + +import Debug = require("debug"); +const debug = Debug("lpf2hub"); + + +/** + * The PUPRemote is emitted if the discovered device is a Powered Up Remote. + * @class PUPRemote + * @extends LPF2Hub + */ +export class PUPRemote extends LPF2Hub { + + + public static IsPUPRemote (peripheral: Peripheral) { + return (peripheral.advertisement.serviceUuids.indexOf(Consts.BLEServices.BOOST_MOVE_HUB) >= 0 && peripheral.advertisement.manufacturerData[3] === Consts.BLEManufacturerData.POWERED_UP_REMOTE_ID); + } + + + constructor (peripheral: Peripheral, autoSubscribe: boolean = true) { + super(peripheral, autoSubscribe); + this.type = Consts.Hubs.POWERED_UP_REMOTE; + this._ports = { + "LEFT": new Port("LEFT", 0), + "RIGHT": new Port("RIGHT", 1) + }; + debug("Discovered Powered Up Remote"); + } + + + public connect () { + return new Promise(async (resolve, reject) => { + debug("Connecting to Powered Up Remote"); + await super.connect(); + debug("Connect completed"); + return resolve(); + }); + } + + + /** + * Set the color of the LED on the Remote via a color value. + * @method PUPRemote#setLEDColor + * @param {number} color A number representing one of the LED color consts. + * @returns {Promise} Resolved upon successful issuance of command. + */ + public setLEDColor (color: number | boolean) { + return new Promise((resolve, reject) => { + if (color === false) { + color = 0; + } + const data = Buffer.from([0x08, 0x00, 0x81, 0x34, 0x11, 0x51, 0x00, color]); + this._writeMessage(Consts.BLECharacteristics.BOOST_ALL, data); + return resolve(); + }); + } + + +} diff --git a/wedo2hub.ts b/wedo2hub.ts index 82d0889..7cb937e 100644 --- a/wedo2hub.ts +++ b/wedo2hub.ts @@ -1,7 +1,7 @@ import { Peripheral } from "noble"; -import { Hub } from "./hub.js"; -import { Port } from "./port.js"; +import { Hub } from "./hub"; +import { Port } from "./port"; import * as Consts from "./consts";