Bug fixes, hubs now wait for hub properties before being connected
This commit is contained in:
parent
bc644c85b2
commit
035017617e
37
examples/multiple_motors.js
Normal file
37
examples/multiple_motors.js
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
*
|
||||
* This demonstrates connecting multiple hubs to your laptop. Once connected, all the hubs LED lights will cycle through the same colors simultaneously.
|
||||
*
|
||||
*/
|
||||
|
||||
const PoweredUP = require("..");
|
||||
|
||||
const poweredUP = new PoweredUP.PoweredUP();
|
||||
poweredUP.scan(); // Start scanning for hubs
|
||||
|
||||
console.log("Looking for Hubs...");
|
||||
|
||||
poweredUP.on("discover", async (hub) => { // Wait to discover hubs
|
||||
|
||||
await hub.connect(); // Connect to hub
|
||||
console.log(`Connected to ${hub.name}!`);
|
||||
|
||||
const motorA = await hub.waitForDeviceAtPort("A");
|
||||
console.log("Got motor A");
|
||||
const motorB = await hub.waitForDeviceAtPort("B");
|
||||
console.log("Got motor B");
|
||||
const motorC = await hub.waitForDeviceAtPort("C");
|
||||
console.log("Got motor C");
|
||||
const motorD = await hub.waitForDeviceAtPort("D");
|
||||
console.log("Got motor D");
|
||||
|
||||
motorA.setPower(30);
|
||||
motorB.setPower(30);
|
||||
motorC.setPower(30);
|
||||
motorD.setPower(30);
|
||||
|
||||
hub.on("disconnect", () => {
|
||||
console.log("Hub disconnected");
|
||||
});
|
||||
|
||||
});
|
@ -41,7 +41,7 @@ export class HubLED extends Device {
|
||||
public setRGB (red: number, green: number, blue: number) {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.subscribe(HubLED.Mode.RGB);
|
||||
this.writeDirect(0x00, Buffer.from([red, green, blue]));
|
||||
this.writeDirect(0x01, Buffer.from([red, green, blue]));
|
||||
return resolve();
|
||||
});
|
||||
}
|
||||
|
@ -54,10 +54,11 @@ export class BaseHub extends EventEmitter {
|
||||
|
||||
private _type: Consts.HubType;
|
||||
private _portMap: {[portName: string]: number} = {};
|
||||
private _attachCallbacks: ((device: Device) => void)[] = [];
|
||||
private _attachCallbacks: ((device: Device) => boolean)[] = [];
|
||||
|
||||
constructor (device: IBLEAbstraction, portMap: {[portName: string]: number} = {}, type: Consts.HubType = Consts.HubType.UNKNOWN) {
|
||||
super();
|
||||
this.setMaxListeners(20); // Technic Medium Hub has 9 built in devices + 4 external ports. Node.js throws a warning after 11 attached event listeners.
|
||||
this._type = type;
|
||||
this._bleDevice = device;
|
||||
this._portMap = portMap;
|
||||
@ -183,7 +184,7 @@ export class BaseHub extends EventEmitter {
|
||||
|
||||
public getDeviceAtPort (portName: string) {
|
||||
const portId = this._portMap[portName];
|
||||
if (portId) {
|
||||
if (portId !== undefined) {
|
||||
return this._attachedDevices[portId];
|
||||
} else {
|
||||
throw new Error(`Port ${portName} does not exist on this hub type`);
|
||||
@ -199,7 +200,10 @@ export class BaseHub extends EventEmitter {
|
||||
}
|
||||
this._attachCallbacks.push((device) => {
|
||||
if (device.portName === portName) {
|
||||
return resolve(device);
|
||||
resolve(device);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -224,7 +228,10 @@ export class BaseHub extends EventEmitter {
|
||||
}
|
||||
this._attachCallbacks.push((device) => {
|
||||
if (device.type === deviceType) {
|
||||
return resolve(device);
|
||||
resolve(device);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
});
|
||||
@ -289,9 +296,15 @@ export class BaseHub extends EventEmitter {
|
||||
* @param {Device} device
|
||||
*/
|
||||
this.emit("attach", device);
|
||||
this._attachCallbacks.forEach((callback) => {
|
||||
callback(device);
|
||||
});
|
||||
debug(`Attached device type ${device.type} (${Consts.DeviceTypeNames[device.type]}) on port ${device.portName} (${device.portId})`);
|
||||
|
||||
let i = this._attachCallbacks.length;
|
||||
while (i--) {
|
||||
const callback = this._attachCallbacks[i];
|
||||
if (callback(device)) {
|
||||
this._attachCallbacks.splice(i, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -303,6 +316,7 @@ export class BaseHub extends EventEmitter {
|
||||
* @param {Device} device
|
||||
*/
|
||||
this.emit("detach", device);
|
||||
debug(`Detached device type ${device.type} (${Consts.DeviceTypeNames[device.type]}) on port ${device.portName} (${device.portId})`);
|
||||
}
|
||||
|
||||
|
||||
|
@ -17,20 +17,24 @@ export class LPF2Hub extends BaseHub {
|
||||
|
||||
private _messageBuffer: Buffer = Buffer.alloc(0);
|
||||
|
||||
private _propertyRequestCallbacks: {[property: number]: ((data: Buffer) => void)} = {};
|
||||
|
||||
|
||||
public connect () {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
debug("LPF2Hub connecting");
|
||||
await super.connect();
|
||||
await this._bleDevice.discoverCharacteristicsForService(Consts.BLEService.LPF2_HUB);
|
||||
this._bleDevice.subscribeToCharacteristic(Consts.BLECharacteristic.LPF2_ALL, this._parseMessage.bind(this));
|
||||
await this.sleep(100);
|
||||
this.send(Buffer.from([0x01, 0x02, 0x02]), Consts.BLECharacteristic.LPF2_ALL); // Activate button reports
|
||||
this.send(Buffer.from([0x01, 0x03, 0x05]), Consts.BLECharacteristic.LPF2_ALL); // Request firmware version
|
||||
this.send(Buffer.from([0x01, 0x04, 0x05]), Consts.BLECharacteristic.LPF2_ALL); // Request hardware version
|
||||
this.send(Buffer.from([0x01, 0x05, 0x02]), Consts.BLECharacteristic.LPF2_ALL); // Activate RSSI updates
|
||||
this.send(Buffer.from([0x01, 0x06, 0x02]), Consts.BLECharacteristic.LPF2_ALL); // Activate battery level reports
|
||||
this.send(Buffer.from([0x01, 0x0d, 0x05]), Consts.BLECharacteristic.LPF2_ALL); // Request primary MAC address
|
||||
await this.sleep(500);
|
||||
this._requestHubPropertyReports(0x02); // Activate button reports
|
||||
await this._requestHubPropertyValue(0x03); // Request firmware version
|
||||
await this._requestHubPropertyValue(0x04); // Request hardware version
|
||||
this._requestHubPropertyReports(0x05); // Activate RSSI updates
|
||||
this._requestHubPropertyReports(0x06); // Activate battery level reports
|
||||
await this._requestHubPropertyValue(0x0d); // Request primary MAC address
|
||||
this.emit("connect");
|
||||
debug("LPF2Hub connected");
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
@ -131,7 +135,12 @@ export class LPF2Hub extends BaseHub {
|
||||
|
||||
switch (message[2]) {
|
||||
case 0x01: {
|
||||
this._parseDeviceInfo(message);
|
||||
const property = message[3];
|
||||
const callback = this._propertyRequestCallbacks[property];
|
||||
if (callback) {
|
||||
callback(message);
|
||||
}
|
||||
delete this._propertyRequestCallbacks[property];
|
||||
break;
|
||||
}
|
||||
case 0x04: {
|
||||
@ -164,7 +173,23 @@ export class LPF2Hub extends BaseHub {
|
||||
}
|
||||
|
||||
|
||||
private _parseDeviceInfo (message: Buffer) {
|
||||
private _requestHubPropertyValue (property: number) {
|
||||
return new Promise((resolve) => {
|
||||
this._propertyRequestCallbacks[property] = (message) => {
|
||||
this._parseHubPropertyResponse(message);
|
||||
return resolve();
|
||||
};
|
||||
this.send(Buffer.from([0x01, property, 0x05]), Consts.BLECharacteristic.LPF2_ALL);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private _requestHubPropertyReports (property: number) {
|
||||
this.send(Buffer.from([0x01, property, 0x02]), Consts.BLECharacteristic.LPF2_ALL);
|
||||
}
|
||||
|
||||
|
||||
private _parseHubPropertyResponse (message: Buffer) {
|
||||
|
||||
// Button press reports
|
||||
if (message[3] === 0x02) {
|
||||
@ -356,45 +381,6 @@ export class LPF2Hub extends BaseHub {
|
||||
device.receive(message);
|
||||
}
|
||||
|
||||
// if ((data[3] === 0x3d && this.type === Consts.HubType.CONTROL_PLUS_HUB)) { // Control+ CPU Temperature
|
||||
// /**
|
||||
// * Emits when a change is detected on a temperature sensor. Measured in degrees centigrade.
|
||||
// * @event LPF2Hub#temp
|
||||
// * @param {string} port For Control+ Hubs, port will be "CPU" as the sensor reports CPU temperature.
|
||||
// * @param {number} temp
|
||||
// */
|
||||
// this.emit("temp", "CPU", ((data.readInt16LE(4) / 900) * 90).toFixed(2));
|
||||
// return;
|
||||
// }
|
||||
|
||||
// const port = this._getPortForPortNumber(data[3]);
|
||||
|
||||
// if (!port) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// if (port && port.connected) {
|
||||
// switch (port.type) {
|
||||
// case Consts.DeviceType.DUPLO_TRAIN_BASE_COLOR: {
|
||||
// if (data[4] <= 10) {
|
||||
// this.emit("color", port.id, data[4]);
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
// case Consts.DeviceType.DUPLO_TRAIN_BASE_SPEEDOMETER: {
|
||||
// /**
|
||||
// * Emits on a speed change.
|
||||
// * @event LPF2Hub#speed
|
||||
// * @param {string} port
|
||||
// * @param {number} speed
|
||||
// */
|
||||
// const speed = data.readInt16LE(4);
|
||||
// this.emit("speed", port.id, speed);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user