diff --git a/examples/light_matrix.js b/examples/light_matrix.js index 1de6174..35976f9 100644 --- a/examples/light_matrix.js +++ b/examples/light_matrix.js @@ -22,7 +22,7 @@ poweredUP.on("discover", async (hub) => { // Wait to discover hubs // setMatrix accepts an array of 9 items - Either standard color values (number), or Color objects with brightness (brightness values are 0 to 100%) // It can also accept just a single color to set all 9 lights to the same color matrix.setMatrix([ - // Red at 100%, green at 20%, red at 200% + // Red at 100%, green at 20%, red at 100% PoweredUP.Consts.Color.RED, new PoweredUP.Color(PoweredUP.Consts.Color.GREEN, 20), PoweredUP.Consts.Color.RED, // Green at 100%, yellow at 100%, green at 100% PoweredUP.Consts.Color.GREEN, PoweredUP.Consts.Color.YELLOW, PoweredUP.Consts.Color.GREEN, diff --git a/src/consts.ts b/src/consts.ts index 638cfe3..268caa8 100644 --- a/src/consts.ts +++ b/src/consts.ts @@ -3,11 +3,12 @@ * @property {number} UNKNOWN 0 * @property {number} WEDO2_SMART_HUB 1 * @property {number} MOVE_HUB 2 - * @property {number} POWERED_UP_HUB 3 - * @property {number} POWERED_UP_REMOTE 4 - * @property {number} DUPLO_TRAIN_HUB 5 - * @property {number} CONTROL_PLUS_HUB 6 + * @property {number} HUB 3 + * @property {number} REMOTE_CONTROL 4 + * @property {number} DUPLO_TRAIN_BASE 5 + * @property {number} TECHNIC_MEDIUM_HUB 6 * @property {number} MARIO 7 + * @property {number} TECHNIC_SMALL_HUB 8 */ export enum HubType { UNKNOWN = 0, @@ -31,27 +32,42 @@ export const HubTypeNames = HubType; * @property {number} UNKNOWN 0 * @property {number} SIMPLE_MEDIUM_LINEAR_MOTOR 1 * @property {number} TRAIN_MOTOR 2 - * @property {number} LED_LIGHTS 8 - * @property {number} VOLTAGE 20 - * @property {number} CURRENT 21 - * @property {number} PIEZO_TONE 22 - * @property {number} RGB_LIGHT 23 - * @property {number} WEDO2_TILT 34 - * @property {number} WEDO2_DISTANCE 35 + * @property {number} LIGHT 8 + * @property {number} VOLTAGE_SENSOR 20 + * @property {number} CURRENT_SENSOR 21 + * @property {number} PIEZO_BUZZER 22 + * @property {number} HUB_LED 23 + * @property {number} TILT_SENSOR 34 + * @property {number} MOTION_SENSOR 35 * @property {number} COLOR_DISTANCE_SENSOR 37 * @property {number} MEDIUM_LINEAR_MOTOR 38 * @property {number} MOVE_HUB_MEDIUM_LINEAR_MOTOR 39 - * @property {number} BOOST_TILT 40 + * @property {number} MOVE_HUB_TILT_SENSOR 40 * @property {number} DUPLO_TRAIN_BASE_MOTOR 41 * @property {number} DUPLO_TRAIN_BASE_SPEAKER 42 - * @property {number} DUPLO_TRAIN_BASE_COLOR 43 + * @property {number} DUPLO_TRAIN_BASE_COLOR_SENSOR 43 * @property {number} DUPLO_TRAIN_BASE_SPEEDOMETER 44 - * @property {number} CONTROL_PLUS_LARGE_MOTOR 46 - * @property {number} CONTROL_PLUS_XLARGE_MOTOR 47 - * @property {number} POWERED_UP_REMOTE_BUTTON 55 - * @property {number} RSSI 56 - * @property {number} CONTROL_PLUS_ACCELEROMETER 58 - * @property {number} CONTROL_PLUS_TILT 59 + * @property {number} TECHNIC_LARGE_LINEAR_MOTOR 46 + * @property {number} TECHNIC_XLARGE_LINEAR_MOTOR 47 + * @property {number} TECHNIC_MEDIUM_ANGULAR_MOTOR 48 + * @property {number} TECHNIC_LARGE_ANGULAR_MOTOR 49 + * @property {number} TECHNIC_MEDIUM_HUB_GEST_SENSOR 54 + * @property {number} REMOTE_CONTROL_BUTTON 55 + * @property {number} REMOTE_CONTROL_RSSI 56 + * @property {number} TECHNIC_MEDIUM_HUB_ACCELEROMETER 57 + * @property {number} TECHNIC_MEDIUM_HUB_GYRO_SENSOR 58 + * @property {number} TECHNIC_MEDIUM_HUB_TILT_SENSOR 59 + * @property {number} TECHNIC_MEDIUM_HUB_TEMPERATURE_SENSOR 60 + * @property {number} TECHNIC_COLOR_SENSOR 61 + * @property {number} TECHNIC_DISTANCE_SENSOR 62 + * @property {number} TECHNIC_FORCE_SENSOR 63 + * @property {number} TECHNIC_3X3_COLOR_LIGHT_MATRIX 64 + * @property {number} TECHNIC_SMALL_ANGULAR_MOTOR 65 + * @property {number} MARIO_ACCELEROMETER 71 + * @property {number} MARIO_BARCODE_SENSOR 73 + * @property {number} MARIO_PANTS_SENSOR 74 + * @property {number} TECHNIC_MEDIUM_ANGULAR_MOTOR_GREY 75 + * @property {number} TECHNIC_LARGE_ANGULAR_MOTOR_GREY 76 */ export enum DeviceType { UNKNOWN = 0, @@ -137,11 +153,11 @@ export const ColorNames = Color; /** * @typedef ButtonState - * @property {number} PRESSED 0 - * @property {number} RELEASED 1 - * @property {number} UP 2 - * @property {number} DOWN 3 - * @property {number} STOP 4 + * @property {number} PRESSED 2 + * @property {number} RELEASED 0 + * @property {number} UP 1 + * @property {number} DOWN 255 + * @property {number} STOP 127 */ export enum ButtonState { PRESSED = 2, @@ -154,6 +170,7 @@ export enum ButtonState { /** * @typedef BrakingStyle + * @property {number} FLOAT 0 * @property {number} HOLD 127 * @property {number} BRAKE 128 */ diff --git a/src/devices/colordistancesensor.ts b/src/devices/colordistancesensor.ts index fc3e85f..367d378 100644 --- a/src/devices/colordistancesensor.ts +++ b/src/devices/colordistancesensor.ts @@ -54,6 +54,74 @@ export class ColorDistanceSensor extends Device { } break; + case Mode.DISTANCE_COUNT: + if (this.isWeDo2SmartHub) { + break; + } + if (message.length !== 8) { + // if mode of device has not changed to this._mode yet + break; + } + const count = message.readUInt32LE(4); + /** + * Emits when distance is reduced to less than 10 centimeters. + * @event ColorDistanceSensor#distanceCount + * @type {object} + * @param {number} number of distance events. + */ + this.notify("distanceCount", { count }); + break; + + case Mode.REFLECT: + if (this.isWeDo2SmartHub) { + break; + } + const reflect = message[4]; + /** + * Event measuring reflection change, emits when the sensor is activated. + * @event ColorDistanceSensor#reflect + * @type {object} + * @param {number} percentage from 0 to 100. + */ + this.notify("reflect", { reflect }); + break; + + case Mode.AMBIENT: + if (this.isWeDo2SmartHub) { + break; + } + const ambient = message[4]; + /** + * Event measuring abient light change, emits when the sensor is activated. + * @event ColorDistanceSensor#ambient + * @type {object} + * @param {number} percentage from 0 to 100. + */ + this.notify("ambient", { ambient }); + break; + + case Mode.RGB_I: + if (this.isWeDo2SmartHub) { + break; + } + if (message.length !== 10) { + // if mode of device has not changed to this._mode yet + break; + } + const red = message.readUInt16LE(4); + const green = message.readUInt16LE(6); + const blue = message.readUInt16LE(8); + /** + * Emits when a color sensor is activated. + * @event ColorDistanceSensor#rgbIntensity + * @type {object} + * @param {number} red + * @param {number} green + * @param {number} blue + */ + this.notify("rgbIntensity", { red, green, blue }); + break; + case Mode.COLOR_AND_DISTANCE: if (this.isWeDo2SmartHub) { break; @@ -193,18 +261,40 @@ export class ColorDistanceSensor extends Device { }); } + /** + * Set the distance count value. + * @method ColorDistanceSensor#setDistanceCount + * @param {count} distance count between 0 and 2^32 + * @returns {Promise} Resolved upon successful issuance of the command. + */ + public setDistanceCount (count: number) { + return new Promise((resolve) => { + if (this.isWeDo2SmartHub) { + throw new Error("Setting distance count is not available on the WeDo 2.0 Smart Hub"); + } else { + const payload = Buffer.alloc(4); + payload.writeUInt32LE(count % 2**32); + // no need to subscribe, can be set in different mode + this.writeDirect(0x02, payload); + } + return resolve(); + }); + } private _pfPowerToPWM (power: number) { return power & 15; } - } export enum Mode { COLOR = 0x00, DISTANCE = 0x01, + DISTANCE_COUNT = 0x02, + REFLECT = 0x03, + AMBIENT = 0x04, LED = 0x05, + RGB_I = 0x06, PF_IR = 0x07, COLOR_AND_DISTANCE = 0x08 } @@ -212,6 +302,10 @@ export enum Mode { export const ModeMap: {[event: string]: number} = { "color": Mode.COLOR, "distance": Mode.DISTANCE, + "distanceCount": Mode.DISTANCE_COUNT, + "reflect": Mode.REFLECT, + "ambient": Mode.AMBIENT, + "rgbIntensity": Mode.RGB_I, "colorAndDistance": Mode.COLOR_AND_DISTANCE }; diff --git a/src/devices/technicmediumhubtiltsensor.ts b/src/devices/technicmediumhubtiltsensor.ts index b421a72..e9f64e2 100644 --- a/src/devices/technicmediumhubtiltsensor.ts +++ b/src/devices/technicmediumhubtiltsensor.ts @@ -10,6 +10,9 @@ import * as Consts from "../consts"; */ export class TechnicMediumHubTiltSensor extends Device { + protected _impactThreshold: number = 10; // guess of default value + protected _impactHoldoff: number = 10; // guess of default value + constructor (hub: IDeviceInterface, portId: number) { super(hub, portId, ModeMap, Consts.DeviceType.TECHNIC_MEDIUM_HUB_TILT_SENSOR); } @@ -21,26 +24,95 @@ export class TechnicMediumHubTiltSensor extends Device { case Mode.TILT: /** * Emits when a tilt sensor is activated. + * * @event TechnicMediumHubTiltSensor#tilt * @type {object} * @param {number} x * @param {number} y * @param {number} z */ - const z = -message.readInt16LE(4); + let z = -message.readInt16LE(4); const y = message.readInt16LE(6); const x = message.readInt16LE(8); + + // workaround for calibration problem or bug in technicMediumHub firmware 1.1.00.0000 + if(y === 90 || y === -90) { + z = Math.sign(y)*(z + 180); + if(z > 180) z -= 360; + if(z < -180) z += 360; + } + this.notify("tilt", { x, y, z }); break; + + case Mode.IMPACT_COUNT: + if (message.length !== 8) { + // if mode of device has not changed to this._mode yet + break; + } + const count = message.readUInt32LE(4); + /** + * Emits when proper acceleration is above threshold (e.g. on impact when being thrown to the ground). + * @event TechnicMediumHubTiltSensor#impactCount + * @type {object} + * @param {number} number of impact events. + */ + this.notify("tiltCount", { count }); + break; } } + /** + * Set the impact count value. + * @method TechnicMediumHubTiltSensor#setImpactCount + * @param {count} impact count between 0 and 2^32 + * @returns {Promise} Resolved upon successful issuance of the command. + */ + public setImpactCount (count: number) { + return new Promise((resolve) => { + const payload = Buffer.alloc(4); + payload.writeUInt32LE(count % 2**32); + // no need to subscribe, can be set in different mode + this.writeDirect(0x01, payload); + return resolve(); + }); + } + + /** + * Set the impact threshold. + * @method TechnicMediumHubTiltSensor#setImpactThreshold + * @param {threshold} value between 1 and 127 + * @returns {Promise} Resolved upon successful issuance of the command. + */ + public setImpactThreshold (threshold: number) { + this._impactThreshold = threshold; + return new Promise((resolve) => { + this.writeDirect(0x02, Buffer.from([this._impactThreshold, this._impactHoldoff])); + return resolve(); + }); + } + + /** + * Set the impact holdoff time. + * @method TechnicMediumHubTiltSensor#setImpactHoldoff + * @param {holdoff} value between 1 and 127 + * @returns {Promise} Resolved upon successful issuance of the command. + */ + public setImpactHoldoff (holdoff: number) { + this._impactHoldoff = holdoff; + return new Promise((resolve) => { + this.writeDirect(0x02, Buffer.from([this._impactThreshold, this._impactHoldoff])); + return resolve(); + }); + } } export enum Mode { - TILT = 0x00 + TILT = 0x00, + IMPACT_COUNT = 0x01 } export const ModeMap: {[event: string]: number} = { - "tilt": Mode.TILT + "tilt": Mode.TILT, + "impactCount": Mode.IMPACT_COUNT };