Skip to content

Commit

Permalink
fix(bluetooth-classic): enforce time limit for inquiries
Browse files Browse the repository at this point in the history
Inquiries that were taking too long could block later inquiries, now
they are correctly terminated in time and the Bluetooth socket is reset.
  • Loading branch information
mKeRix committed Feb 28, 2020
1 parent 169754b commit f9a1ae4
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,17 @@ describe('BluetoothClassicService', () => {
expect(service.inquireRssi('08:05:90:ed:3b:60')).resolves.toBeUndefined();
});

it('should return reset the HCI device if the query took too long', async () => {
const execMock = jest.fn().mockRejectedValue({ signal: 'SIGKILL' });
jest.spyOn(util, 'promisify').mockImplementation(() => {
return execMock;
});

const result = await service.inquireRssi('08:05:90:ed:3b:60');
expect(result).toBeUndefined();
expect(execMock).toHaveBeenCalledWith('hciconfig hci0 reset');
});

it('should return device information based on parsed output', async () => {
jest.spyOn(util, 'promisify').mockImplementation(() => {
return jest.fn().mockResolvedValue({
Expand Down
27 changes: 25 additions & 2 deletions src/integrations/bluetooth-classic/bluetooth-classic.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,13 +175,23 @@ export class BluetoothClassicService extends KalmanFilterable(Object, 1.4, 1)
this.logger.debug(`Querying for RSSI of ${address} using hcitool`);
try {
const output = await execPromise(
`hcitool cc "${address}" && hcitool rssi "${address}"`
`hcitool cc "${address}" && hcitool rssi "${address}"`,
{
timeout: 5.5 * 1000,
killSignal: 'SIGKILL'
}
);
const matches = output.stdout.match(regex);

return matches?.length > 0 ? parseInt(matches[0], 10) : undefined;
} catch (e) {
this.logger.debug(e.message);
if (e.signal === 'SIGKILL') {
this.logger.warn(`Query of ${address} took too long, resetting hci0`);
this.resetHciDevice();
} else {
this.logger.debug(e.message);
}

return undefined;
}
}
Expand Down Expand Up @@ -250,6 +260,19 @@ export class BluetoothClassicService extends KalmanFilterable(Object, 1.4, 1)
return this.inquiriesSwitch?.state;
}

/**
* Reset the hci (Bluetooth) device used for inquiries.
*/
protected async resetHciDevice(): Promise<void> {
const execPromise = util.promisify(exec);

try {
await execPromise('hciconfig hci0 reset');
} catch (e) {
this.logger.error(e.message);
}
}

/**
* Creates and registers a new switch as a setting for whether Bluetooth queries should be made from this device or not.
*
Expand Down

0 comments on commit f9a1ae4

Please sign in to comment.