Seperated BLEDevice out into NobleDevice and WebBLEDevice usingi nterfaces
This commit is contained in:
parent
6f8f5bbaf8
commit
f23e5ad679
@ -5585,7 +5585,7 @@
|
||||
<span class="jsdoc-message">
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a>
|
||||
|
||||
on Thu Feb 7th 2019
|
||||
on Mon Mar 18th 2019
|
||||
|
||||
using the <a href="https://github.com/docstrap/docstrap">DocStrap template</a>.
|
||||
</span>
|
||||
|
@ -4188,7 +4188,7 @@
|
||||
<span class="jsdoc-message">
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a>
|
||||
|
||||
on Thu Feb 7th 2019
|
||||
on Mon Mar 18th 2019
|
||||
|
||||
using the <a href="https://github.com/docstrap/docstrap">DocStrap template</a>.
|
||||
</span>
|
||||
|
@ -2467,7 +2467,7 @@
|
||||
<span class="jsdoc-message">
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a>
|
||||
|
||||
on Thu Feb 7th 2019
|
||||
on Mon Mar 18th 2019
|
||||
|
||||
using the <a href="https://github.com/docstrap/docstrap">DocStrap template</a>.
|
||||
</span>
|
||||
|
@ -4444,7 +4444,7 @@
|
||||
<span class="jsdoc-message">
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a>
|
||||
|
||||
on Thu Feb 7th 2019
|
||||
on Mon Mar 18th 2019
|
||||
|
||||
using the <a href="https://github.com/docstrap/docstrap">DocStrap template</a>.
|
||||
</span>
|
||||
|
@ -5157,7 +5157,7 @@
|
||||
<span class="jsdoc-message">
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a>
|
||||
|
||||
on Thu Feb 7th 2019
|
||||
on Mon Mar 18th 2019
|
||||
|
||||
using the <a href="https://github.com/docstrap/docstrap">DocStrap template</a>.
|
||||
</span>
|
||||
|
@ -3409,7 +3409,7 @@
|
||||
<span class="jsdoc-message">
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a>
|
||||
|
||||
on Thu Feb 7th 2019
|
||||
on Mon Mar 18th 2019
|
||||
|
||||
using the <a href="https://github.com/docstrap/docstrap">DocStrap template</a>.
|
||||
</span>
|
||||
|
@ -1018,7 +1018,7 @@
|
||||
<span class="jsdoc-message">
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a>
|
||||
|
||||
on Thu Feb 7th 2019
|
||||
on Mon Mar 18th 2019
|
||||
|
||||
using the <a href="https://github.com/docstrap/docstrap">DocStrap template</a>.
|
||||
</span>
|
||||
|
@ -5158,7 +5158,7 @@
|
||||
<span class="jsdoc-message">
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a>
|
||||
|
||||
on Thu Feb 7th 2019
|
||||
on Mon Mar 18th 2019
|
||||
|
||||
using the <a href="https://github.com/docstrap/docstrap">DocStrap template</a>.
|
||||
</span>
|
||||
|
@ -351,7 +351,7 @@ exports.BoostMoveHub = BoostMoveHub;
|
||||
<span class="jsdoc-message">
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a>
|
||||
|
||||
on Thu Feb 7th 2019
|
||||
on Mon Mar 18th 2019
|
||||
|
||||
using the <a href="https://github.com/docstrap/docstrap">DocStrap template</a>.
|
||||
</span>
|
||||
|
@ -6681,7 +6681,7 @@
|
||||
<span class="jsdoc-message">
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a>
|
||||
|
||||
on Thu Feb 7th 2019
|
||||
on Mon Mar 18th 2019
|
||||
|
||||
using the <a href="https://github.com/docstrap/docstrap">DocStrap template</a>.
|
||||
</span>
|
||||
|
@ -282,7 +282,7 @@ var BLECharacteristic;
|
||||
<span class="jsdoc-message">
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a>
|
||||
|
||||
on Thu Feb 7th 2019
|
||||
on Mon Mar 18th 2019
|
||||
|
||||
using the <a href="https://github.com/docstrap/docstrap">DocStrap template</a>.
|
||||
</span>
|
||||
|
@ -300,7 +300,7 @@ exports.DuploTrainBase = DuploTrainBase;
|
||||
<span class="jsdoc-message">
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a>
|
||||
|
||||
on Thu Feb 7th 2019
|
||||
on Mon Mar 18th 2019
|
||||
|
||||
using the <a href="https://github.com/docstrap/docstrap">DocStrap template</a>.
|
||||
</span>
|
||||
|
@ -3272,7 +3272,7 @@
|
||||
<span class="jsdoc-message">
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a>
|
||||
|
||||
on Thu Feb 7th 2019
|
||||
on Mon Mar 18th 2019
|
||||
|
||||
using the <a href="https://github.com/docstrap/docstrap">DocStrap template</a>.
|
||||
</span>
|
||||
|
@ -448,7 +448,7 @@ exports.Hub = Hub;
|
||||
<span class="jsdoc-message">
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a>
|
||||
|
||||
on Thu Feb 7th 2019
|
||||
on Mon Mar 18th 2019
|
||||
|
||||
using the <a href="https://github.com/docstrap/docstrap">DocStrap template</a>.
|
||||
</span>
|
||||
|
@ -314,7 +314,7 @@ poweredUP.scan(); // Start scanning for Hubs</code></pre><p>More examples are av
|
||||
<span class="jsdoc-message">
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a>
|
||||
|
||||
on Thu Feb 7th 2019
|
||||
on Mon Mar 18th 2019
|
||||
|
||||
using the <a href="https://github.com/docstrap/docstrap">DocStrap template</a>.
|
||||
</span>
|
||||
|
@ -503,7 +503,7 @@ exports.LPF2Hub = LPF2Hub;
|
||||
<span class="jsdoc-message">
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a>
|
||||
|
||||
on Thu Feb 7th 2019
|
||||
on Mon Mar 18th 2019
|
||||
|
||||
using the <a href="https://github.com/docstrap/docstrap">DocStrap template</a>.
|
||||
</span>
|
||||
|
@ -93,9 +93,9 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const bledevice_1 = require("./bledevice");
|
||||
const boostmovehub_1 = require("./boostmovehub");
|
||||
const duplotrainbase_1 = require("./duplotrainbase");
|
||||
const nobledevice_1 = require("./nobledevice");
|
||||
const puphub_1 = require("./puphub");
|
||||
const pupremote_1 = require("./pupremote");
|
||||
const wedo2smarthub_1 = require("./wedo2smarthub");
|
||||
@ -193,7 +193,7 @@ class PoweredUP extends events_1.EventEmitter {
|
||||
return Object.keys(this._connectedHubs).map((uuid) => this._connectedHubs[uuid]).filter((hub) => hub.name === name);
|
||||
}
|
||||
async _discoveryEventHandler(peripheral) {
|
||||
const device = new bledevice_1.BLEDevice(peripheral);
|
||||
const device = new nobledevice_1.NobleDevice(peripheral);
|
||||
let hub;
|
||||
if (await wedo2smarthub_1.WeDo2SmartHub.IsWeDo2SmartHub(peripheral)) {
|
||||
hub = new wedo2smarthub_1.WeDo2SmartHub(device, this.autoSubscribe);
|
||||
@ -286,7 +286,7 @@ exports.PoweredUP = PoweredUP;
|
||||
<span class="jsdoc-message">
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a>
|
||||
|
||||
on Thu Feb 7th 2019
|
||||
on Mon Mar 18th 2019
|
||||
|
||||
using the <a href="https://github.com/docstrap/docstrap">DocStrap template</a>.
|
||||
</span>
|
||||
|
@ -308,7 +308,7 @@ exports.PUPHub = PUPHub;
|
||||
<span class="jsdoc-message">
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a>
|
||||
|
||||
on Thu Feb 7th 2019
|
||||
on Mon Mar 18th 2019
|
||||
|
||||
using the <a href="https://github.com/docstrap/docstrap">DocStrap template</a>.
|
||||
</span>
|
||||
|
@ -238,7 +238,7 @@ exports.PUPRemote = PUPRemote;
|
||||
<span class="jsdoc-message">
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a>
|
||||
|
||||
on Thu Feb 7th 2019
|
||||
on Mon Mar 18th 2019
|
||||
|
||||
using the <a href="https://github.com/docstrap/docstrap">DocStrap template</a>.
|
||||
</span>
|
||||
|
File diff suppressed because one or more lines are too long
@ -540,7 +540,7 @@ exports.WeDo2SmartHub = WeDo2SmartHub;
|
||||
<span class="jsdoc-message">
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a>
|
||||
|
||||
on Thu Feb 7th 2019
|
||||
on Mon Mar 18th 2019
|
||||
|
||||
using the <a href="https://github.com/docstrap/docstrap">DocStrap template</a>.
|
||||
</span>
|
||||
|
237
src/bledevice.ts
237
src/bledevice.ts
@ -1,237 +0,0 @@
|
||||
import { Characteristic, Peripheral, Service } from "noble";
|
||||
|
||||
import Debug = require("debug");
|
||||
import { EventEmitter } from "events";
|
||||
import { write } from "fs";
|
||||
const debug = Debug("bledevice");
|
||||
|
||||
|
||||
export class BLEDevice extends EventEmitter {
|
||||
|
||||
// @ts-ignore
|
||||
private _noblePeripheral: Peripheral | null;
|
||||
private _webBLEServer: any;
|
||||
|
||||
private _uuid: string;
|
||||
private _name: string = "";
|
||||
|
||||
private _listeners: {[uuid: string]: any} = {};
|
||||
private _characteristics: {[uuid: string]: Characteristic} = {};
|
||||
|
||||
private _queue: Promise<any> = Promise.resolve();
|
||||
private _mailbox: Buffer[] = [];
|
||||
|
||||
private _connected: boolean = false;
|
||||
private _connecting: boolean = false;
|
||||
|
||||
|
||||
constructor (device: any) {
|
||||
super();
|
||||
if (device._noble) {
|
||||
this._noblePeripheral = device;
|
||||
this._uuid = device.uuid;
|
||||
device.on("disconnect", () => {
|
||||
this._connected = false;
|
||||
this._connected = false;
|
||||
this.emit("disconnect");
|
||||
});
|
||||
// NK: This hack allows LPF2.0 hubs to send a second advertisement packet consisting of the hub name before we try to read it
|
||||
setTimeout(() => {
|
||||
this._name = device.advertisement.localName;
|
||||
this.emit("discoverComplete");
|
||||
}, 1000);
|
||||
} else {
|
||||
this._webBLEServer = device;
|
||||
this._uuid = device.device.id;
|
||||
this._name = device.device.name;
|
||||
device.device.addEventListener("gattserverdisconnected", () => {
|
||||
this._connected = false;
|
||||
this._connected = false;
|
||||
this.emit("disconnect");
|
||||
});
|
||||
setTimeout(() => {
|
||||
this.emit("discoverComplete");
|
||||
}, 2000);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public get uuid () {
|
||||
return this._uuid;
|
||||
}
|
||||
|
||||
|
||||
public get name () {
|
||||
return this._name;
|
||||
}
|
||||
|
||||
|
||||
public get connecting () {
|
||||
return this._connecting;
|
||||
}
|
||||
|
||||
|
||||
public get connected () {
|
||||
return this._connected;
|
||||
}
|
||||
|
||||
|
||||
public connect () {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (this._noblePeripheral) {
|
||||
this._connecting = true;
|
||||
this._noblePeripheral.connect((err: string) => {
|
||||
this._connecting = false;
|
||||
this._connected = true;
|
||||
return resolve();
|
||||
});
|
||||
} else {
|
||||
this._connected = true;
|
||||
return resolve();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public disconnect () {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (this._noblePeripheral) {
|
||||
this._noblePeripheral.connect((err: string) => {
|
||||
return resolve();
|
||||
});
|
||||
} else {
|
||||
this._webBLEServer.device.gatt.disconnect();
|
||||
return resolve();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public discoverCharacteristicsForService (uuid: string) {
|
||||
return new Promise(async (discoverResolve, discoverReject) => {
|
||||
if (this._noblePeripheral) {
|
||||
uuid = this._sanitizeUUID(uuid);
|
||||
this._noblePeripheral.discoverServices([uuid], (err: string, services: Service[]) => {
|
||||
if (err) {
|
||||
return discoverReject(err);
|
||||
}
|
||||
debug("Service/characteristic discovery started");
|
||||
const servicePromises: Array<Promise<null>> = [];
|
||||
services.forEach((service) => {
|
||||
servicePromises.push(new Promise((resolve, reject) => {
|
||||
service.discoverCharacteristics([], (err, characteristics) => {
|
||||
characteristics.forEach((characteristic) => {
|
||||
this._characteristics[characteristic.uuid] = characteristic;
|
||||
});
|
||||
return resolve();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
Promise.all(servicePromises).then(() => {
|
||||
debug("Service/characteristic discovery finished");
|
||||
return discoverResolve();
|
||||
});
|
||||
});
|
||||
} else if (this._webBLEServer) {
|
||||
debug("Service/characteristic discovery started");
|
||||
let service;
|
||||
try {
|
||||
service = await this._webBLEServer.getPrimaryService(uuid);
|
||||
} catch (err) {
|
||||
return discoverReject(err);
|
||||
}
|
||||
const characteristics = await service.getCharacteristics();
|
||||
for (const characteristic of characteristics) {
|
||||
this._characteristics[characteristic.uuid] = characteristic;
|
||||
}
|
||||
debug("Service/characteristic discovery finished");
|
||||
return discoverResolve();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public subscribeToCharacteristic (uuid: string, callback: (data: Buffer) => void) {
|
||||
if (this._noblePeripheral) {
|
||||
uuid = this._sanitizeUUID(uuid);
|
||||
this._characteristics[uuid].on("data", (data: Buffer) => {
|
||||
return callback(data);
|
||||
});
|
||||
this._characteristics[uuid].subscribe((err) => {
|
||||
if (err) {
|
||||
throw new Error(err);
|
||||
}
|
||||
});
|
||||
} else if (this._webBLEServer) {
|
||||
if (this._listeners[uuid]) {
|
||||
// @ts-ignore
|
||||
this._characteristics[uuid].removeEventListener("characteristicvaluechanged", this._listeners[uuid]);
|
||||
}
|
||||
// @ts-ignore
|
||||
this._listeners[uuid] = (event) => {
|
||||
const buf = Buffer.alloc(event.target.value.buffer.byteLength);
|
||||
const view = new Uint8Array(event.target.value.buffer);
|
||||
for (let i = 0; i < buf.length; i++) {
|
||||
buf[i] = view[i];
|
||||
}
|
||||
return callback(buf);
|
||||
};
|
||||
// @ts-ignore
|
||||
this._characteristics[uuid].addEventListener("characteristicvaluechanged", this._listeners[uuid]);
|
||||
for (const data of this._mailbox) {
|
||||
callback(data);
|
||||
}
|
||||
this._mailbox = [];
|
||||
// @ts-ignore
|
||||
this._characteristics[uuid].startNotifications();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public addToCharacteristicMailbox (uuid: string, data: Buffer) {
|
||||
this._mailbox.push(data);
|
||||
}
|
||||
|
||||
|
||||
public readFromCharacteristic (uuid: string, callback: (err: string | null, data: Buffer | null) => void) {
|
||||
if (this._noblePeripheral) {
|
||||
uuid = this._sanitizeUUID(uuid);
|
||||
this._characteristics[uuid].read((err: string, data: Buffer) => {
|
||||
return callback(err, data);
|
||||
});
|
||||
} else if (this._webBLEServer) {
|
||||
// @ts-ignore
|
||||
this._characteristics[uuid].readValue().then((data) => {
|
||||
const buf = Buffer.alloc(data.buffer.byteLength);
|
||||
const view = new Uint8Array(data.buffer);
|
||||
for (let i = 0; i < buf.length; i++) {
|
||||
buf[i] = view[i];
|
||||
}
|
||||
callback(null, buf);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public writeToCharacteristic (uuid: string, data: Buffer, callback?: () => void) {
|
||||
if (this._noblePeripheral) {
|
||||
uuid = this._sanitizeUUID(uuid);
|
||||
this._characteristics[uuid].write(data, false, callback);
|
||||
} else {
|
||||
// @ts-ignore
|
||||
this._queue = this._queue.then(() => this._characteristics[uuid].writeValue(data)).then(() => {
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private _sanitizeUUID (uuid: string) {
|
||||
return uuid.replace(/-/g, "");
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,12 +1,12 @@
|
||||
import { Peripheral } from "noble";
|
||||
|
||||
import { BLEDevice } from "./bledevice";
|
||||
import { LPF2Hub } from "./lpf2hub";
|
||||
import { Port } from "./port";
|
||||
|
||||
import * as Consts from "./consts";
|
||||
|
||||
import Debug = require("debug");
|
||||
import { IBLEDevice } from "./interfaces";
|
||||
const debug = Debug("boostmovehub");
|
||||
|
||||
|
||||
@ -34,7 +34,7 @@ export class BoostMoveHub extends LPF2Hub {
|
||||
}
|
||||
|
||||
|
||||
constructor (device: BLEDevice, autoSubscribe: boolean = true) {
|
||||
constructor (device: IBLEDevice, autoSubscribe: boolean = true) {
|
||||
super(device, autoSubscribe);
|
||||
this.type = Consts.HubType.BOOST_MOVE_HUB;
|
||||
this._ports = {
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { Peripheral } from "noble";
|
||||
|
||||
import { BLEDevice } from "./bledevice";
|
||||
import { LPF2Hub } from "./lpf2hub";
|
||||
import { Port } from "./port";
|
||||
|
||||
import * as Consts from "./consts";
|
||||
|
||||
import Debug = require("debug");
|
||||
import { IBLEDevice } from "./interfaces";
|
||||
const debug = Debug("duplotrainbase");
|
||||
|
||||
|
||||
@ -64,7 +64,7 @@ export class DuploTrainBase extends LPF2Hub {
|
||||
}
|
||||
|
||||
|
||||
constructor (device: BLEDevice, autoSubscribe: boolean = true) {
|
||||
constructor (device: IBLEDevice, autoSubscribe: boolean = true) {
|
||||
super(device, autoSubscribe);
|
||||
this.type = Consts.HubType.DUPLO_TRAIN_HUB;
|
||||
this._ports = {
|
||||
|
14
src/hub.ts
14
src/hub.ts
@ -1,6 +1,6 @@
|
||||
import { EventEmitter } from "events";
|
||||
|
||||
import { BLEDevice } from "./bledevice";
|
||||
import { IBLEDevice, IFirmwareInfo } from "./interfaces";
|
||||
import { Port } from "./port";
|
||||
|
||||
import * as Consts from "./consts";
|
||||
@ -9,14 +9,6 @@ import Debug = require("debug");
|
||||
const debug = Debug("hub");
|
||||
|
||||
|
||||
export interface IFirmwareInfo {
|
||||
major: number;
|
||||
minor: number;
|
||||
bugFix: number;
|
||||
build: number;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @class Hub
|
||||
* @extends EventEmitter
|
||||
@ -36,13 +28,13 @@ export class Hub extends EventEmitter {
|
||||
protected _voltage: number = 0;
|
||||
protected _current: number = 0;
|
||||
|
||||
protected _bleDevice: BLEDevice;
|
||||
protected _bleDevice: IBLEDevice;
|
||||
private _rssi: number = -100;
|
||||
|
||||
private _isConnecting = false;
|
||||
private _isConnected = false;
|
||||
|
||||
constructor (device: BLEDevice, autoSubscribe: boolean = true) {
|
||||
constructor (device: IBLEDevice, autoSubscribe: boolean = true) {
|
||||
super();
|
||||
this.autoSubscribe = !!autoSubscribe;
|
||||
this._bleDevice = device;
|
||||
|
23
src/interfaces.ts
Normal file
23
src/interfaces.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import { EventEmitter } from "events";
|
||||
|
||||
export interface IFirmwareInfo {
|
||||
major: number;
|
||||
minor: number;
|
||||
bugFix: number;
|
||||
build: number;
|
||||
}
|
||||
|
||||
|
||||
export interface IBLEDevice extends EventEmitter {
|
||||
uuid: string;
|
||||
name: string;
|
||||
connecting: boolean;
|
||||
connected: boolean;
|
||||
connect: () => Promise<any>;
|
||||
disconnect: () => Promise<any>;
|
||||
discoverCharacteristicsForService: (uuid: string) => Promise<any>;
|
||||
subscribeToCharacteristic: (uuid: string, callback: (data: Buffer) => void) => void;
|
||||
addToCharacteristicMailbox: (uuid: string, data: Buffer) => void;
|
||||
readFromCharacteristic: (uuid: string, callback: (err: string | null, data: Buffer | null) => void) => void;
|
||||
writeToCharacteristic: (uuid: string, data: Buffer, callback?: () => void) => void;
|
||||
}
|
150
src/nobledevice.ts
Normal file
150
src/nobledevice.ts
Normal file
@ -0,0 +1,150 @@
|
||||
import { Characteristic, Peripheral, Service } from "noble";
|
||||
|
||||
import Debug = require("debug");
|
||||
import { EventEmitter } from "events";
|
||||
import { IBLEDevice } from "./interfaces";
|
||||
const debug = Debug("bledevice");
|
||||
|
||||
|
||||
export class NobleDevice extends EventEmitter implements IBLEDevice {
|
||||
|
||||
private _noblePeripheral: Peripheral;
|
||||
|
||||
private _uuid: string;
|
||||
private _name: string = "";
|
||||
|
||||
private _listeners: {[uuid: string]: any} = {};
|
||||
private _characteristics: {[uuid: string]: Characteristic} = {};
|
||||
|
||||
private _queue: Promise<any> = Promise.resolve();
|
||||
private _mailbox: Buffer[] = [];
|
||||
|
||||
private _connected: boolean = false;
|
||||
private _connecting: boolean = false;
|
||||
|
||||
|
||||
constructor (device: any) {
|
||||
super();
|
||||
this._noblePeripheral = device;
|
||||
this._uuid = device.uuid;
|
||||
device.on("disconnect", () => {
|
||||
this._connected = false;
|
||||
this._connected = false;
|
||||
this.emit("disconnect");
|
||||
});
|
||||
// NK: This hack allows LPF2.0 hubs to send a second advertisement packet consisting of the hub name before we try to read it
|
||||
setTimeout(() => {
|
||||
this._name = device.advertisement.localName;
|
||||
this.emit("discoverComplete");
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
|
||||
public get uuid () {
|
||||
return this._uuid;
|
||||
}
|
||||
|
||||
|
||||
public get name () {
|
||||
return this._name;
|
||||
}
|
||||
|
||||
|
||||
public get connecting () {
|
||||
return this._connecting;
|
||||
}
|
||||
|
||||
|
||||
public get connected () {
|
||||
return this._connected;
|
||||
}
|
||||
|
||||
|
||||
public connect () {
|
||||
return new Promise((resolve, reject) => {
|
||||
this._connecting = true;
|
||||
this._noblePeripheral.connect((err: string) => {
|
||||
this._connecting = false;
|
||||
this._connected = true;
|
||||
return resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public disconnect () {
|
||||
return new Promise((resolve, reject) => {
|
||||
this._noblePeripheral.connect((err: string) => {
|
||||
return resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public discoverCharacteristicsForService (uuid: string) {
|
||||
return new Promise(async (discoverResolve, discoverReject) => {
|
||||
uuid = this._sanitizeUUID(uuid);
|
||||
this._noblePeripheral.discoverServices([uuid], (err: string, services: Service[]) => {
|
||||
if (err) {
|
||||
return discoverReject(err);
|
||||
}
|
||||
debug("Service/characteristic discovery started");
|
||||
const servicePromises: Array<Promise<null>> = [];
|
||||
services.forEach((service) => {
|
||||
servicePromises.push(new Promise((resolve, reject) => {
|
||||
service.discoverCharacteristics([], (err, characteristics) => {
|
||||
characteristics.forEach((characteristic) => {
|
||||
this._characteristics[characteristic.uuid] = characteristic;
|
||||
});
|
||||
return resolve();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
Promise.all(servicePromises).then(() => {
|
||||
debug("Service/characteristic discovery finished");
|
||||
return discoverResolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public subscribeToCharacteristic (uuid: string, callback: (data: Buffer) => void) {
|
||||
uuid = this._sanitizeUUID(uuid);
|
||||
this._characteristics[uuid].on("data", (data: Buffer) => {
|
||||
return callback(data);
|
||||
});
|
||||
this._characteristics[uuid].subscribe((err) => {
|
||||
if (err) {
|
||||
throw new Error(err);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public addToCharacteristicMailbox (uuid: string, data: Buffer) {
|
||||
this._mailbox.push(data);
|
||||
}
|
||||
|
||||
|
||||
public readFromCharacteristic (uuid: string, callback: (err: string | null, data: Buffer | null) => void) {
|
||||
uuid = this._sanitizeUUID(uuid);
|
||||
this._characteristics[uuid].read((err: string, data: Buffer) => {
|
||||
return callback(err, data);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public writeToCharacteristic (uuid: string, data: Buffer, callback?: () => void) {
|
||||
uuid = this._sanitizeUUID(uuid);
|
||||
this._characteristics[uuid].write(data, false, callback);
|
||||
}
|
||||
|
||||
|
||||
private _sanitizeUUID (uuid: string) {
|
||||
return uuid.replace(/-/g, "");
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
import { BLEDevice } from "./bledevice";
|
||||
import { BoostMoveHub } from "./boostmovehub";
|
||||
import { DuploTrainBase } from "./duplotrainbase";
|
||||
import { Hub } from "./hub";
|
||||
import { PUPHub } from "./puphub";
|
||||
import { PUPRemote } from "./pupremote";
|
||||
import { WebBLEDevice } from "./webbledevice";
|
||||
import { WeDo2SmartHub } from "./wedo2smarthub";
|
||||
|
||||
import * as Consts from "./consts";
|
||||
@ -11,7 +11,7 @@ import * as Consts from "./consts";
|
||||
import { EventEmitter } from "events";
|
||||
|
||||
import Debug = require("debug");
|
||||
import { LPF2Hub } from "./lpf2hub";
|
||||
import { IBLEDevice } from "./interfaces";
|
||||
const debug = Debug("poweredup");
|
||||
|
||||
|
||||
@ -99,7 +99,7 @@ export class PoweredUP extends EventEmitter {
|
||||
}
|
||||
|
||||
|
||||
private _determineLPF2HubType (device: BLEDevice) {
|
||||
private _determineLPF2HubType (device: IBLEDevice): Promise<Consts.HubType> {
|
||||
return new Promise((resolve, reject) => {
|
||||
let buf: Buffer = Buffer.alloc(0);
|
||||
device.subscribeToCharacteristic(Consts.BLECharacteristic.LPF2_ALL, (data: Buffer) => {
|
||||
@ -137,7 +137,7 @@ export class PoweredUP extends EventEmitter {
|
||||
|
||||
private async _discoveryEventHandler (server: BluetoothRemoteGATTServer) {
|
||||
|
||||
const device = new BLEDevice(server);
|
||||
const device = new WebBLEDevice(server);
|
||||
|
||||
let hub: Hub;
|
||||
|
||||
@ -157,7 +157,6 @@ export class PoweredUP extends EventEmitter {
|
||||
} catch (error) {}
|
||||
|
||||
if (isLPF2Hub) {
|
||||
// @ts-ignore
|
||||
hubType = await this._determineLPF2HubType(device);
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { Peripheral } from "noble-mac";
|
||||
|
||||
import { BLEDevice } from "./bledevice";
|
||||
import { BoostMoveHub } from "./boostmovehub";
|
||||
import { DuploTrainBase } from "./duplotrainbase";
|
||||
import { Hub } from "./hub";
|
||||
import { NobleDevice } from "./nobledevice";
|
||||
import { PUPHub } from "./puphub";
|
||||
import { PUPRemote } from "./pupremote";
|
||||
import { WeDo2SmartHub } from "./wedo2smarthub";
|
||||
@ -130,7 +130,7 @@ export class PoweredUP extends EventEmitter {
|
||||
|
||||
private async _discoveryEventHandler (peripheral: Peripheral) {
|
||||
|
||||
const device = new BLEDevice(peripheral);
|
||||
const device = new NobleDevice(peripheral);
|
||||
|
||||
let hub: Hub;
|
||||
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { Peripheral } from "noble";
|
||||
|
||||
import { BLEDevice } from "./bledevice";
|
||||
import { LPF2Hub } from "./lpf2hub";
|
||||
import { Port } from "./port";
|
||||
|
||||
import * as Consts from "./consts";
|
||||
|
||||
import Debug = require("debug");
|
||||
import { IBLEDevice } from "./interfaces";
|
||||
const debug = Debug("puphub");
|
||||
|
||||
|
||||
@ -39,7 +39,7 @@ export class PUPHub extends LPF2Hub {
|
||||
}
|
||||
|
||||
|
||||
constructor (device: BLEDevice, autoSubscribe: boolean = true) {
|
||||
constructor (device: IBLEDevice, autoSubscribe: boolean = true) {
|
||||
super(device, autoSubscribe);
|
||||
this.type = Consts.HubType.POWERED_UP_HUB;
|
||||
this._ports = {
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { Peripheral } from "noble";
|
||||
|
||||
import { BLEDevice } from "./bledevice";
|
||||
import { LPF2Hub } from "./lpf2hub";
|
||||
import { Port } from "./port";
|
||||
|
||||
import * as Consts from "./consts";
|
||||
|
||||
import Debug = require("debug");
|
||||
import { IBLEDevice } from "./interfaces";
|
||||
const debug = Debug("pupremote");
|
||||
|
||||
|
||||
@ -64,7 +64,7 @@ export class PUPRemote extends LPF2Hub {
|
||||
}
|
||||
|
||||
|
||||
constructor (device: BLEDevice, autoSubscribe: boolean = true) {
|
||||
constructor (device: IBLEDevice, autoSubscribe: boolean = true) {
|
||||
super(device, autoSubscribe);
|
||||
this.type = Consts.HubType.POWERED_UP_REMOTE;
|
||||
this._ports = {
|
||||
|
149
src/webbledevice.ts
Normal file
149
src/webbledevice.ts
Normal file
@ -0,0 +1,149 @@
|
||||
import Debug = require("debug");
|
||||
import { EventEmitter } from "events";
|
||||
import { IBLEDevice } from "./interfaces";
|
||||
const debug = Debug("bledevice");
|
||||
|
||||
|
||||
export class WebBLEDevice extends EventEmitter implements IBLEDevice {
|
||||
|
||||
private _webBLEServer: any;
|
||||
|
||||
private _uuid: string;
|
||||
private _name: string = "";
|
||||
|
||||
private _listeners: {[uuid: string]: any} = {};
|
||||
private _characteristics: {[uuid: string]: any} = {};
|
||||
|
||||
private _queue: Promise<any> = Promise.resolve();
|
||||
private _mailbox: Buffer[] = [];
|
||||
|
||||
private _connected: boolean = false;
|
||||
private _connecting: boolean = false;
|
||||
|
||||
|
||||
constructor (device: any) {
|
||||
super();
|
||||
this._webBLEServer = device;
|
||||
this._uuid = device.device.id;
|
||||
this._name = device.device.name;
|
||||
device.device.addEventListener("gattserverdisconnected", () => {
|
||||
this._connected = false;
|
||||
this._connected = false;
|
||||
this.emit("disconnect");
|
||||
});
|
||||
setTimeout(() => {
|
||||
this.emit("discoverComplete");
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
|
||||
public get uuid () {
|
||||
return this._uuid;
|
||||
}
|
||||
|
||||
|
||||
public get name () {
|
||||
return this._name;
|
||||
}
|
||||
|
||||
|
||||
public get connecting () {
|
||||
return this._connecting;
|
||||
}
|
||||
|
||||
|
||||
public get connected () {
|
||||
return this._connected;
|
||||
}
|
||||
|
||||
|
||||
public connect () {
|
||||
return new Promise((resolve, reject) => {
|
||||
this._connected = true;
|
||||
return resolve();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public disconnect () {
|
||||
return new Promise((resolve, reject) => {
|
||||
this._webBLEServer.device.gatt.disconnect();
|
||||
return resolve();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public discoverCharacteristicsForService (uuid: string) {
|
||||
return new Promise(async (discoverResolve, discoverReject) => {
|
||||
debug("Service/characteristic discovery started");
|
||||
let service;
|
||||
try {
|
||||
service = await this._webBLEServer.getPrimaryService(uuid);
|
||||
} catch (err) {
|
||||
return discoverReject(err);
|
||||
}
|
||||
const characteristics = await service.getCharacteristics();
|
||||
for (const characteristic of characteristics) {
|
||||
this._characteristics[characteristic.uuid] = characteristic;
|
||||
}
|
||||
debug("Service/characteristic discovery finished");
|
||||
return discoverResolve();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public subscribeToCharacteristic (uuid: string, callback: (data: Buffer) => void) {
|
||||
if (this._listeners[uuid]) {
|
||||
this._characteristics[uuid].removeEventListener("characteristicvaluechanged", this._listeners[uuid]);
|
||||
}
|
||||
// @ts-ignore
|
||||
this._listeners[uuid] = (event) => {
|
||||
const buf = Buffer.alloc(event.target.value.buffer.byteLength);
|
||||
const view = new Uint8Array(event.target.value.buffer);
|
||||
for (let i = 0; i < buf.length; i++) {
|
||||
buf[i] = view[i];
|
||||
}
|
||||
return callback(buf);
|
||||
};
|
||||
this._characteristics[uuid].addEventListener("characteristicvaluechanged", this._listeners[uuid]);
|
||||
for (const data of this._mailbox) {
|
||||
callback(data);
|
||||
}
|
||||
this._mailbox = [];
|
||||
this._characteristics[uuid].startNotifications();
|
||||
}
|
||||
|
||||
|
||||
public addToCharacteristicMailbox (uuid: string, data: Buffer) {
|
||||
this._mailbox.push(data);
|
||||
}
|
||||
|
||||
|
||||
public readFromCharacteristic (uuid: string, callback: (err: string | null, data: Buffer | null) => void) {
|
||||
// @ts-ignore
|
||||
this._characteristics[uuid].readValue().then((data) => {
|
||||
const buf = Buffer.alloc(data.buffer.byteLength);
|
||||
const view = new Uint8Array(data.buffer);
|
||||
for (let i = 0; i < buf.length; i++) {
|
||||
buf[i] = view[i];
|
||||
}
|
||||
callback(null, buf);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public writeToCharacteristic (uuid: string, data: Buffer, callback?: () => void) {
|
||||
this._queue = this._queue.then(() => this._characteristics[uuid].writeValue(data)).then(() => {
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private _sanitizeUUID (uuid: string) {
|
||||
return uuid.replace(/-/g, "");
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,12 +1,12 @@
|
||||
import { Peripheral } from "noble";
|
||||
|
||||
import { BLEDevice } from "./bledevice";
|
||||
import { Hub } from "./hub";
|
||||
import { Port } from "./port";
|
||||
|
||||
import * as Consts from "./consts";
|
||||
|
||||
import Debug = require("debug");
|
||||
import { IBLEDevice } from "./interfaces";
|
||||
import { isBrowserContext } from "./utils";
|
||||
const debug = Debug("wedo2smarthub");
|
||||
|
||||
@ -38,7 +38,7 @@ export class WeDo2SmartHub extends Hub {
|
||||
private _lastTiltY: number = 0;
|
||||
|
||||
|
||||
constructor (device: BLEDevice, autoSubscribe: boolean = true) {
|
||||
constructor (device: IBLEDevice, autoSubscribe: boolean = true) {
|
||||
super(device, autoSubscribe);
|
||||
this.type = Consts.HubType.WEDO2_SMART_HUB;
|
||||
this._ports = {
|
||||
|
Loading…
x
Reference in New Issue
Block a user