node-poweredup/src/devices/colordistancesensor.ts

176 lines
5.8 KiB
TypeScript

import { Device } from "./device";
import { IDeviceInterface } from "../interfaces";
import * as Consts from "../consts";
/**
* @class ColorDistanceSensor
* @extends Device
*/
export class ColorDistanceSensor extends Device {
constructor (hub: IDeviceInterface, portId: number) {
super(hub, portId, ModeMap, Consts.DeviceType.COLOR_DISTANCE_SENSOR);
}
public receive (message: Buffer) {
const mode = this._mode;
switch (mode) {
case Mode.COLOR:
if (message[this.isWeDo2SmartHub ? 2 : 4] <= 10) {
const color = message[this.isWeDo2SmartHub ? 2 : 4];
/**
* Emits when a color sensor is activated.
* @event ColorDistanceSensor#color
* @type {object}
* @param {Color} color
*/
this.notify("color", { color });
}
break;
case Mode.DISTANCE:
if (this.isWeDo2SmartHub) {
break;
}
if (message[4] <= 10) {
const distance = Math.floor(message[4] * 25.4) - 20;
/**
* Emits when a distance sensor is activated.
* @event ColorDistanceSensor#distance
* @type {object}
* @param {number} distance Distance, in millimeters.
*/
this.notify("distance", { distance });
}
break;
case Mode.COLOR_AND_DISTANCE:
if (this.isWeDo2SmartHub) {
break;
}
let distance = message[5];
const partial = message[7];
if (partial > 0) {
distance += 1.0 / partial;
}
distance = Math.floor(distance * 25.4) - 20;
/**
* A combined color and distance event, emits when the sensor is activated.
* @event ColorDistanceSensor#colorAndDistance
* @type {object}
* @param {Color} color
* @param {number} distance Distance, in millimeters.
*/
if (message[4] <= 10) {
const color = message[4];
this.notify("colorAndDistance", { color, distance });
}
break;
}
}
/**
* Set the power of a Power Functions motor via IR
* @method ColorDistanceSensor#sendPFIRMessage
* @param {number} channel Channel number, between 1-4
* @param {string} output Outport port, "RED" (A) or "BLUE" (B)
* @param {number} power -7 (full reverse) to 7 (full forward). 0 is stop. 8 is brake.
* @returns {Promise} Resolved upon successful issuance of the command.
*/
public setPFPower (channel: number, output: string, power: number) {
const message = Buffer.alloc(2);
// Send "Single output mode"
message[0] = ((channel - 1) << 4) + (output === "RED" ? 4 : 5);
message[1] = this._pfPowerToPWM(power) << 4;
this.sendPFIRMessage(message);
}
/**
* Start Power Functions motors running via IR
*
* NOTE: This command is designed for bang-bang style operation. To keep the motors running, the sensor needs to be within range of the IR receiver constantly.
* @method ColorDistanceSensor#sendPFIRMessage
* @param {Buffer} channel Channel number, between 1-4
* @param {Buffer} powerA -7 (full reverse) to 7 (full forward). 0 is stop. 8 is brake.
* @param {Buffer} powerB -7 (full reverse) to 7 (full forward). 0 is stop. 8 is brake.
* @returns {Promise} Resolved upon successful issuance of the command.
*/
public startPFMotors (channel: number, powerA: number, powerB: number) {
const message = Buffer.alloc(2);
// Send "Combo PWD mode"
message[0] = (((channel - 1) + 4) << 4) + this._pfPowerToPWM(powerA);
message[1] += this._pfPowerToPWM(powerB) << 4;
this.sendPFIRMessage(message);
}
/**
* Send a raw Power Functions IR command
* @method ColorDistanceSensor#sendPFIRMessage
* @param {Buffer} message 2 byte payload making up a Power Functions protocol command. NOTE: Only specify nibbles 1-3, nibble 4 should be zeroed.
* @returns {Promise} Resolved upon successful issuance of the command.
*/
public sendPFIRMessage (message: Buffer) {
const payload = Buffer.alloc(2);
payload[0] = (message[0] << 4) + (message[1] >> 4);
payload[1] = message[0] >> 4;
this.subscribe(Mode.PF_IR);
this.writeDirect(0x07, payload);
}
/**
* Set the color of the LED on the sensor via a color value.
* @method ColorDistanceSensor#setColor
* @param {Color} color
* @returns {Promise} Resolved upon successful issuance of the command.
*/
public setColor (color: number | boolean) {
return new Promise((resolve, reject) => {
if (typeof color === "boolean") {
color = 0;
}
if (this.isWeDo2SmartHub) {
throw new Error("Setting LED color is not available on the WeDo 2.0 Smart Hub");
} else {
this.subscribe(Mode.LED);
this.writeDirect(0x05, Buffer.from([color]));
}
return resolve();
});
}
private _pfPowerToPWM (power: number) {
return (power < 0 ? 16 + power : power);
}
}
export enum Mode {
COLOR = 0x00,
DISTANCE = 0x01,
LED = 0x05,
PF_IR = 0x07,
COLOR_AND_DISTANCE = 0x08
}
export const ModeMap: {[event: string]: number} = {
"color": Mode.COLOR,
"distance": Mode.DISTANCE,
"colorAndDistance": Mode.COLOR_AND_DISTANCE
};