Skip to content

Commit

Permalink
Fix Bluetooth stop function GladysAssistant#1093 (GladysAssistant#1097)
Browse files Browse the repository at this point in the history
Co-authored-by: Pierre-Gilles Leymarie <pierregilles.leymarie@gmail.com>
  • Loading branch information
2 people authored and Jean-Philippe Danrée committed Aug 27, 2021
1 parent 0339b35 commit 5d512ed
Show file tree
Hide file tree
Showing 8 changed files with 82 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ class BluetoothSettingsTab extends Component {
<button
class="btn btn-outline-primary"
onClick={this.scanPresence}
disabled={saving || bluetoothStatus.scanning}
disabled={saving || bluetoothStatus.scanning || !bluetoothStatus.ready}
>
<i class="fe fe-radio mr-2" />
<Text id="integration.bluetooth.setup.presenceScannerButton" />
Expand Down
4 changes: 2 additions & 2 deletions server/services/bluetooth/lib/commands/bluetooth.getStatus.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
* bluetooth.getStatus();
*/
function getStatus() {
const { ready, scanning, peripheralLookup } = this;
const { ready, scanning, peripheralLookup, bluetooth } = this;
const status = {
ready,
ready: bluetooth !== undefined && ready,
scanning,
peripheralLookup,
};
Expand Down
2 changes: 1 addition & 1 deletion server/services/bluetooth/lib/commands/bluetooth.scan.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ async function scan(state, peripheralUuid = undefined) {
this.bluetooth.startScanning([], true);
}

this.scanTimer = Promise.delay(TIMERS.SCAN).then(() => this.bluetooth.stopScanning());
this.scanPromise = Promise.delay(TIMERS.SCAN).then(() => this.bluetooth.stopScanning());
});
}

Expand Down
19 changes: 18 additions & 1 deletion server/services/bluetooth/lib/commands/bluetooth.stop.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,28 @@ const logger = require('../../../../utils/logger');
async function stop() {
this.discoveredDevices = {};

const { timer } = this.presenceScanner;
if (timer) {
logger.info(`Bluetooth configuration: stopping presence scanner`);
clearInterval(timer);
this.presenceScanner.timer = undefined;
}

logger.debug(`Bluetooth: Stop discovering`);
await this.bluetooth.stopScanningAsync();
this.bluetooth.stopScanning();

logger.debug(`Bluetooth: Removing all Bluetooth listeners`);
this.bluetooth.removeAllListeners();

logger.debug(`Bluetooth: Reset service status`);
this.bluetooth = undefined;

if (this.scanPromise && this.scanPromise.isPending()) {
this.scanPromise.cancel();
}

this.scanPromise = undefined;
this.scanCounter = 0;
}

module.exports = {
Expand Down
2 changes: 1 addition & 1 deletion server/services/bluetooth/lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const BluetoothManager = function BluetoothManager(gladys, serviceId) {
this.gladys = gladys;
this.serviceId = serviceId;

this.scanTimer = undefined;
this.scanPromise = undefined;
this.scanCounter = 0;

this.ready = false;
Expand Down
2 changes: 1 addition & 1 deletion server/test/services/bluetooth/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,6 @@ describe('BluetoothService', () => {
// No more listener
expect(bluetooth.eventNames()).is.lengthOf(0);

assert.calledOnce(bluetooth.stopScanningAsync);
assert.calledOnce(bluetooth.stopScanning);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ describe('bluetooth.getStatus command', () => {
});

it('should get status ready and scanning', () => {
bluetoothManager.bluetooth = 'any';
bluetoothManager.ready = true;
bluetoothManager.scanning = true;
const result = bluetoothManager.getStatus();
Expand All @@ -45,13 +46,22 @@ describe('bluetooth.getStatus command', () => {
});

it('should get status ready not scanning', () => {
bluetoothManager.bluetooth = 'any';
bluetoothManager.ready = true;
bluetoothManager.scanning = false;
const result = bluetoothManager.getStatus();
expect(result).deep.eq({ ready: true, scanning: false, peripheralLookup: false });
assert.notCalled(eventWS);
});

it('should get status not ready (no bluetooth instance)', () => {
bluetoothManager.ready = true;
bluetoothManager.scanning = false;
const result = bluetoothManager.getStatus();
expect(result).deep.eq({ ready: false, scanning: false, peripheralLookup: false });
assert.notCalled(eventWS);
});

it('should get status not ready not scanning', () => {
bluetoothManager.ready = false;
bluetoothManager.scanning = false;
Expand Down
50 changes: 48 additions & 2 deletions server/test/services/bluetooth/lib/commands/bluetooth.stop.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const { expect } = require('chai');
const sinon = require('sinon');

const { assert } = sinon;
const { assert, fake } = sinon;

const BluetoothManager = require('../../../../../services/bluetooth/lib');
const BluetoothMock = require('../../BluetoothMock.test');
Expand All @@ -12,25 +12,71 @@ const serviceId = 'de051f90-f34a-4fd5-be2e-e502339ec9bc';
describe('bluetooth.stop command', () => {
let bluetooth;
let bluetoothManager;
let clock;

beforeEach(() => {
bluetooth = new BluetoothMock();

bluetoothManager = new BluetoothManager(gladys, serviceId);
bluetoothManager.bluetooth = bluetooth;
bluetoothManager.discoveredDevices = { any: 'any' };
bluetoothManager.scanCounter = 12;

clock = sinon.useFakeTimers();
});

afterEach(() => {
bluetooth.removeAllListeners();
clock.restore();
sinon.reset();
});

it('check listeners and peripherals are well removed', async () => {
await bluetoothManager.stop();

expect(bluetoothManager.bluetooth).eq(undefined);
expect(bluetoothManager.discoveredDevices).deep.eq({});
expect(bluetoothManager.scanPromise).eq(undefined);
expect(bluetoothManager.scanCounter).eq(0);

// No more listener
expect(bluetooth.eventNames()).is.lengthOf(0);

assert.calledOnce(bluetooth.stopScanningAsync);
assert.calledOnce(bluetooth.stopScanning);
});

it('check only pending timers are well removed', async () => {
sinon.spy(clock, 'clearInterval');

bluetoothManager.presenceScanner.timer = setInterval(assert.fail, 5000);

const scanPromise = {
isPending: () => false,
cancel: fake.returns(false),
};
bluetoothManager.scanPromise = scanPromise;

await bluetoothManager.stop();

assert.calledOnce(bluetooth.stopScanning);
assert.calledOnce(clock.clearInterval);
assert.notCalled(scanPromise.cancel);
});

it('check timers are well removed', async () => {
sinon.spy(clock, 'clearInterval');

bluetoothManager.presenceScanner.timer = setInterval(assert.fail, 5000);
const scanPromise = {
isPending: () => true,
cancel: fake.returns(false),
};
bluetoothManager.scanPromise = scanPromise;

await bluetoothManager.stop();

assert.calledOnce(bluetooth.stopScanning);
assert.calledOnce(clock.clearInterval);
assert.calledOnce(scanPromise.cancel);
});
});

0 comments on commit 5d512ed

Please sign in to comment.