diff --git a/docs/integrations/bluetooth-classic.md b/docs/integrations/bluetooth-classic.md index cbbaee5..ff74472 100644 --- a/docs/integrations/bluetooth-classic.md +++ b/docs/integrations/bluetooth-classic.md @@ -28,7 +28,7 @@ sudo setcap cap_net_raw+eip $(eval readlink -f `which hcitool`) ## How it works -This integration assumes that you have loaded it and configured it in the same manner on all instances that you want to use for tracking. Every 10 seconds each instance in the cluster will be tasked with querying the signal strength of one of the configured devices. The resulting RSSI values are shared with all other instances, one of which keeps track of all device states. +This integration assumes that you have loaded it and configured it in the same manner on all instances that you want to use for tracking. Every 6 seconds each instance in the cluster will be tasked with querying the signal strength of one of the configured devices. The resulting RSSI values are shared with all other instances, one of which keeps track of all device states. Each configured device will create a sensor that has the name of the closest room-assistant instance as its state - or `not_home` if the device could not be found by any of them. The distance in the attributes of those sensors is the inverted signal strength value and does not actually represent any physical distance. It may also show negative numbers. diff --git a/src/integrations/bluetooth-classic/bluetooth-classic.service.spec.ts b/src/integrations/bluetooth-classic/bluetooth-classic.service.spec.ts index abc2d4a..3d20d4b 100644 --- a/src/integrations/bluetooth-classic/bluetooth-classic.service.spec.ts +++ b/src/integrations/bluetooth-classic/bluetooth-classic.service.spec.ts @@ -128,6 +128,14 @@ describe('BluetoothClassicService', () => { expect(service.inquireRssi('08:05:90:ed:3b:60')).resolves.toBeUndefined(); }); + it('should return undefined if the command failed', () => { + jest.spyOn(util, 'promisify').mockImplementation(() => { + return jest.fn().mockRejectedValue({ message: 'Command failed' }); + }); + + expect(service.inquireRssi('08:05:90:ed:3b:60')).resolves.toBeUndefined(); + }); + it('should return device information based on parsed output', async () => { jest.spyOn(util, 'promisify').mockImplementation(() => { return jest.fn().mockResolvedValue({ diff --git a/src/integrations/bluetooth-classic/bluetooth-classic.service.ts b/src/integrations/bluetooth-classic/bluetooth-classic.service.ts index 0ad48a4..056a54a 100644 --- a/src/integrations/bluetooth-classic/bluetooth-classic.service.ts +++ b/src/integrations/bluetooth-classic/bluetooth-classic.service.ts @@ -119,7 +119,7 @@ export class BluetoothClassicService extends KalmanFilterable(Object, 1.4, 1) * Sends out RSSI requests to the connected nodes in the cluster by matching each one with a MAC address. * Rotates the mapping on each call. */ - @Interval(10 * 1000) + @Interval(6 * 1000) distributeInquiries(): void { if (this.clusterService.isLeader()) { const nodes = this.getParticipatingNodes(); @@ -158,15 +158,20 @@ export class BluetoothClassicService extends KalmanFilterable(Object, 1.4, 1) */ async inquireRssi(address: string): Promise { const execPromise = util.promisify(exec); + const regex = new RegExp(/-?[0-9]+/); this.logger.debug(`Querying for RSSI of ${address} using hcitool`); - const output = await execPromise( - `hcitool cc "${address}" && hcitool rssi "${address}"` - ); - const regex = new RegExp(/-?[0-9]+/); - const matches = output.stdout.match(regex); + try { + const output = await execPromise( + `hcitool cc "${address}" && hcitool rssi "${address}"` + ); + const matches = output.stdout.match(regex); - return matches?.length > 0 ? parseInt(matches[0], 10) : undefined; + return matches?.length > 0 ? parseInt(matches[0], 10) : undefined; + } catch (e) { + this.logger.debug(e.message); + return undefined; + } } /**