Allows more use of await Removed some unnecessary awaits, some unnecessary Promise wrappers
192 lines
5.1 KiB
TypeScript
192 lines
5.1 KiB
TypeScript
import { EventEmitter } from "events";
|
|
|
|
import { IDeviceInterface } from "../interfaces";
|
|
|
|
import * as Consts from "../consts";
|
|
|
|
/**
|
|
* @class Device
|
|
* @extends EventEmitter
|
|
*/
|
|
export class Device extends EventEmitter {
|
|
|
|
public autoSubscribe: boolean = true;
|
|
public values: {[event: string]: any} = {};
|
|
|
|
protected _mode: number | undefined;
|
|
protected _busy: boolean = false;
|
|
protected _finished: (() => void) | undefined;
|
|
|
|
private _hub: IDeviceInterface;
|
|
private _portId: number;
|
|
private _connected: boolean = true;
|
|
private _type: Consts.DeviceType;
|
|
private _modeMap: {[event: string]: number} = {};
|
|
|
|
private _isWeDo2SmartHub: boolean;
|
|
private _isVirtualPort: boolean = false;
|
|
private _eventTimer: NodeJS.Timer | null = null;
|
|
|
|
constructor (hub: IDeviceInterface, portId: number, modeMap: {[event: string]: number} = {}, type: Consts.DeviceType = Consts.DeviceType.UNKNOWN) {
|
|
super();
|
|
this._hub = hub;
|
|
this._portId = portId;
|
|
this._type = type;
|
|
this._modeMap = modeMap;
|
|
this._isWeDo2SmartHub = (this.hub.type === Consts.HubType.WEDO2_SMART_HUB);
|
|
this._isVirtualPort = this.hub.isPortVirtual(portId);
|
|
|
|
const eventAttachListener = (event: string) => {
|
|
if (event === "detach") {
|
|
return;
|
|
}
|
|
if (this.autoSubscribe) {
|
|
if (this._modeMap[event] !== undefined) {
|
|
this.subscribe(this._modeMap[event]);
|
|
}
|
|
}
|
|
};
|
|
|
|
const deviceDetachListener = (device: Device) => {
|
|
if (device.portId === this.portId) {
|
|
this._connected = false;
|
|
this.hub.removeListener("detach", deviceDetachListener);
|
|
this.emit("detach");
|
|
}
|
|
};
|
|
|
|
for (const event in this._modeMap) {
|
|
if (this.hub.listenerCount(event) > 0) {
|
|
eventAttachListener(event);
|
|
}
|
|
}
|
|
|
|
this.hub.on("newListener", eventAttachListener);
|
|
this.on("newListener", eventAttachListener);
|
|
this.hub.on("detach", deviceDetachListener);
|
|
}
|
|
|
|
/**
|
|
* @readonly
|
|
* @property {boolean} connected Check if the device is still attached.
|
|
*/
|
|
public get connected () {
|
|
return this._connected;
|
|
}
|
|
|
|
/**
|
|
* @readonly
|
|
* @property {Hub} hub The Hub the device is attached to.
|
|
*/
|
|
public get hub () {
|
|
return this._hub;
|
|
}
|
|
|
|
public get portId () {
|
|
return this._portId;
|
|
}
|
|
|
|
/**
|
|
* @readonly
|
|
* @property {string} portName The port the device is attached to.
|
|
*/
|
|
public get portName () {
|
|
return this.hub.getPortNameForPortId(this.portId);
|
|
}
|
|
|
|
/**
|
|
* @readonly
|
|
* @property {number} type The type of the device
|
|
*/
|
|
public get type () {
|
|
return this._type;
|
|
}
|
|
|
|
public get typeName () {
|
|
return Consts.DeviceTypeNames[this.type];
|
|
}
|
|
|
|
/**
|
|
* @readonly
|
|
* @property {number} mode The mode the device is currently in
|
|
*/
|
|
public get mode () {
|
|
return this._mode;
|
|
}
|
|
|
|
protected get isWeDo2SmartHub () {
|
|
return this._isWeDo2SmartHub;
|
|
}
|
|
|
|
/**
|
|
* @readonly
|
|
* @property {boolean} isVirtualPort Is this device attached to a virtual port (ie. a combined device)
|
|
*/
|
|
protected get isVirtualPort () {
|
|
return this._isVirtualPort;
|
|
}
|
|
|
|
public writeDirect (mode: number, data: Buffer) {
|
|
if (this.isWeDo2SmartHub) {
|
|
return this.send(Buffer.concat([Buffer.from([this.portId, 0x01, 0x02]), data]), Consts.BLECharacteristic.WEDO2_MOTOR_VALUE_WRITE);
|
|
} else {
|
|
return this.send(Buffer.concat([Buffer.from([0x81, this.portId, 0x11, 0x51, mode]), data]), Consts.BLECharacteristic.LPF2_ALL);
|
|
}
|
|
}
|
|
|
|
public send (data: Buffer, characteristic: string = Consts.BLECharacteristic.LPF2_ALL) {
|
|
this._ensureConnected();
|
|
return this.hub.send(data, characteristic);
|
|
}
|
|
|
|
public subscribe (mode: number) {
|
|
this._ensureConnected();
|
|
if (mode !== this._mode) {
|
|
this._mode = mode;
|
|
this.hub.subscribe(this.portId, this.type, mode);
|
|
}
|
|
}
|
|
|
|
public unsubscribe (mode: number) {
|
|
this._ensureConnected();
|
|
}
|
|
|
|
public receive (message: Buffer) {
|
|
this.notify("receive", { message });
|
|
}
|
|
|
|
public notify (event: string, values: any) {
|
|
this.values[event] = values;
|
|
this.emit(event, values);
|
|
if (this.hub.listenerCount(event) > 0) {
|
|
this.hub.emit(event, this, values);
|
|
}
|
|
}
|
|
|
|
public finish () {
|
|
this._busy = false;
|
|
if (this._finished) {
|
|
this._finished();
|
|
this._finished = undefined;
|
|
}
|
|
}
|
|
|
|
public setEventTimer (timer: NodeJS.Timer) {
|
|
this._eventTimer = timer;
|
|
}
|
|
|
|
public cancelEventTimer () {
|
|
if (this._eventTimer) {
|
|
clearTimeout(this._eventTimer);
|
|
this._eventTimer = null;
|
|
}
|
|
}
|
|
|
|
private _ensureConnected () {
|
|
if (!this.connected) {
|
|
throw new Error("Device is not connected");
|
|
}
|
|
}
|
|
|
|
}
|