Open Bonitis opened 7 years ago
This is not really a full code snippet that can be used to reproduce the issue. HRMDataFromPeripheral
is missing for sure.
An HCI dump should give us some more info as to what's going on sudo hcidump -t -x
Also, what USB adapter are you using?
Here is the adapter info from hciconfig:
hci0: Type: BR/EDR Bus: USB
BD Address: 00:25:BF:70:02:C8 ACL MTU: 310:12 SCO MTU: 64:8
UP RUNNING
RX bytes:374409 acl:1055 sco:0 events:13782 errors:0
TX bytes:3605 acl:55 sco:0 commands:205 errors:0
Features: 0xff 0xff 0x8f 0xfe 0xdb 0xff 0x5b 0x87
Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3
Link policy: RSWITCH HOLD SNIFF PARK
Link mode: SLAVE ACCEPT
Name: 'raspberrypi-2-0'
Class: 0x000000
Service Classes: Unspecified
Device Class: Miscellaneous,
HCI Version: 4.1 (0x7) Revision: 0x2933
LMP Version: 4.1 (0x7) Subversion: 0x2933
Manufacturer: Cambridge Silicon Radio (10)
I have since reworked my code, so here is a more relevant sample
import bleno from 'bleno';
import events from 'events';
import fs from 'fs';
import noble from 'noble';
import util from 'util';
import Log from 'log';
import colors from 'colors'; // eslint-disable-line no-unused-vars
import { size } from 'lodash';
import Constants from '../Constants';
function HRMDataFromPeripheral(hrm) {
if (hrm) {
return {
id: hrm.id,
address: hrm.address,
name: hrm.advertisement.localName,
};
}
}
// starts the noble scanning process to discovery peripherals
const StartScanningForPeripherals = () => {
log.debug('Starting to scan for peripherals');
noble.startScanning(Constants.SERVICE_UUIDS, false, (err) => {
if (err) {
log.error(`startScanning error: ${err}`);
}
});
};
class Tracker {
constructor() {
this.Initialize();
}
Initialize() {
this.SetUpBLE();
}
SetUpBLE() {
noble.on('discover', (peripheral) => {
if (peripheral.state !== 'disconnected') {
return;
}
// eslint-disable-next-line no-underscore-dangle
log.debug(`Noble currently showing ${size(noble._peripherals)} peripherals`);
log.info(`Found device with local name: ${peripheral.advertisement.localName.green}`);
peripheral.once('disconnect', (error) => {
const hrm = HRMDataFromPeripheral(peripheral);
if (error) {
const err = `Error disconnecting from peripheral ${peripheral.advertisement.localName}: ${error}`;
log.error(err);
return;
}
log.info(`${peripheral.advertisement.localName.red} disconnected.`);
StartScanningForPeripherals();
});
peripheral.once('connect', (error) => {
if (error) {
const err = `Peripheral [${peripheral.advertisement.localName}] connection error: ${error}`;
this.DisconnectAndUntrackPeripheral(peripheral, err);
return;
}
log.debug(`Connected to peripheral: ${peripheral.advertisement.localName.green}`);
peripheral.discoverServices([Constants.HEART_RATE_SERVICE_UUID],
(servicesError, services) => {
if (servicesError) {
const err = `Discover services error for ${peripheral.advertisement.localName}: ${error}`;
this.DisconnectAndUntrackPeripheral(peripheral, err);
return;
}
const deviceInformationService = services[0];
if (deviceInformationService === undefined) {
const err = `Error: deviceInformationService for ${peripheral.advertisement.localName.red} not found.`;
this.DisconnectAndUntrackPeripheral(peripheral, err);
return;
}
deviceInformationService.discoverCharacteristics([Constants.HEART_RATE_MEASUREMENT_CHARACTERTISTIC_UUID],
(characteristicsError, characteristics) => {
if (error || characteristicsError) {
const err = `Error: discoverCharacteristics failed for ${peripheral.advertisement.localName}: ${characteristicsError.red}`;
this.DisconnectAndUntrackPeripheral(peripheral, err);
return;
}
const hrCharacteristic = characteristics[0];
if (hrCharacteristic) {
log.debug(`discovered hr measurement characteristic for ${peripheral.advertisement.localName}`);
// subscribe to the HR characteristic and check for errors
hrCharacteristic.subscribe((characteristicError) => {
if (characteristicError) {
const err = `Error with HR characteristic for ${peripheral.advertisement.localName}: ${characteristicError}`;
this.DisconnectAndUntrackPeripheral(peripheral, err);
}
log.info(`hr notification on for ${peripheral.advertisement.localName.green}`);
});
} else {
// there is no HR characteristic, so disconnect to the peripheral, hopefully reconnecting
const err = `Error: no hrCharacteristic found for ${peripheral.advertisement.localName}, disconnecting`;
this.DisconnectAndUntrackPeripheral(peripheral, err);
}
});
});
});
peripheral.connect();
});
noble.on('stateChange', (state) => {
if (state === 'poweredOn') {
log.debug('Bluetooth Powered On, Scanning for devices...'.green);
StartScanningForPeripherals();
} else {
log.info('BLE Antenna state currently', state, '. Waiting for device to Power on.');
// noble.stopScanning();
}
});
noble.on('scanStop', () => {
log.debug('Detected bluetooth scan stop - scanning again');
StartScanningForPeripherals();
});
noble.on('warning', (message) => {
log.warning(`noble warning: ${message}`);
});
}
DisconnectAndUntrackPeripheral(peripheral, error) {
if (error) {
log.error(error);
}
// disconnect from this peripheral
peripheral.disconnect();
// restart scanning to try to pick the device back up
StartScanningForPeripherals();
}
}
util.inherits(Tracker, events.EventEmitter);
module.exports = Tracker;
Constants.js
module.exports.HEART_RATE_SERVICE_UUID = '180d';
module.exports.HEART_RATE_MEASUREMENT_CHARACTERTISTIC_UUID = '2a37';
module.exports.SERVICE_UUIDS = [module.exports.HEART_RATE_SERVICE_UUID];
I don't have a relevant hcidump, but I will try to get you one. With my tweaked code I have not seen the same errors, but I am trying every possible scenario that would trigger an error. I don't know if what I have here is a good way to do it, but it seems to have less problems.
@sandeepmistry here is an hcidump. https://gist.github.com/Bonitis/ca14d7a82f797d2089614d9058bf5b0e
I finally got an hcidump while this command disallowed
issue was happening: https://gist.github.com/Bonitis/b62f0977254ab1b4d3af6a9ecc5cbd86
I'm not really sure what to make of it, but it seems that if it happens to one device, I can't connect any other devices and need to reboot/restart.
Yes, i have this issue as well, one onConnect gives an error, the peripheral is broken, noble no longer detects it, is there a way to recover from onConnect errors?
@Bonitis I got command disallowed with my dongle when I try to connect to device without stopping the scan. You should try stop scanning before connect (carefull of your noble.on('scanStop', () ) method)
@benjaminhon Have a look at my Issue here : https://github.com/sandeepmistry/noble/issues/664 It looks similar to your problem, it may help.
Setup noble: v1.8.0 node: v6.10.0 Raspbian Jessie on Raspberry Pi 3 USB BLE antenna with onboard BT disabled
After I reboot my rPi or restart my node app, I am no longer able to connect to devices, and am given this error:
That is being triggered from my
noble.on('connect')
function, as well as a disconnect function, seen here:If I run
sudo hcitool lescan
then restart the app, it will sometimes fix the problem, but not always. Then, if it is fixed and I can connect to a device, if I turn that device off and back on, I sometimes get the same error. It seems like even though I am callingperipheral.disconnect()
the 'disconnect' event is not firing.How do I best avoid these connection errors, and when they do happen, what is the best way to try connecting to that device again?