diff --git a/config/test.yml b/config/test.yml index 7295687..35f1a66 100644 --- a/config/test.yml +++ b/config/test.yml @@ -2,10 +2,6 @@ global: instanceName: test-instance integrations: - bluetoothLowEnergy -bluetoothClassic: - addresses: - - 8d:ad:e3:e2:7a:01 - - f7:6c:e3:10:55:b5 gpio: binarySensors: - name: PIR Sensor diff --git a/docs/integrations/bluetooth-classic.md b/docs/integrations/bluetooth-classic.md index 2052196..2fde4d3 100644 --- a/docs/integrations/bluetooth-classic.md +++ b/docs/integrations/bluetooth-classic.md @@ -40,9 +40,10 @@ You could use this to reduce the resources used by room-assistant when you are c ## Settings -| Name | Type | Default | Description | -| ----------- | ----- | ------- | ------------------------------------------------------------ | -| `addresses` | Array | | List of Bluetooth MAC addresses that should be tracked. You can usually find them in the device settings. | +| Name | Type | Default | Description | +| ----------- | ------ | ------- | ------------------------------------------------------------ | +| `addresses` | Array | | List of Bluetooth MAC addresses that should be tracked. You can usually find them in the device settings. | +| `minRssi` | Number | | Limits the RSSI at which a device is still reported if configured. Remember, the RSSI is the inverse of the sensor attribute distance, so for a cutoff at 10 you would configure -10. | ::: details Example Config ```yaml @@ -50,6 +51,7 @@ global: integrations: - bluetoothClassic bluetoothClassic: + minRssi: -20 addresses: - '08:05:90:ed:3b:60' - '77:50:fb:4d:ab:70' diff --git a/src/integrations/bluetooth-classic/bluetooth-classic.config.ts b/src/integrations/bluetooth-classic/bluetooth-classic.config.ts index af9de9c..fb3c85e 100644 --- a/src/integrations/bluetooth-classic/bluetooth-classic.config.ts +++ b/src/integrations/bluetooth-classic/bluetooth-classic.config.ts @@ -1,3 +1,4 @@ export class BluetoothClassicConfig { addresses: string[] = []; + minRssi?: number; } diff --git a/src/integrations/bluetooth-classic/bluetooth-classic.service.spec.ts b/src/integrations/bluetooth-classic/bluetooth-classic.service.spec.ts index 3e90766..9d8f71b 100644 --- a/src/integrations/bluetooth-classic/bluetooth-classic.service.spec.ts +++ b/src/integrations/bluetooth-classic/bluetooth-classic.service.spec.ts @@ -15,6 +15,9 @@ import { NewRssiEvent } from './new-rssi.event'; import { RoomPresenceDistanceSensor } from '../room-presence/room-presence-distance.sensor'; import KalmanFilter from 'kalmanjs'; import { Switch } from '../../entities/switch'; +import { BluetoothClassicConfig } from './bluetooth-classic.config'; +import c from 'config'; +import { ConfigService } from '../../config/config.service'; jest.mock('../room-presence/room-presence-distance.sensor'); jest.mock('kalmanjs', () => { @@ -49,6 +52,14 @@ describe('BluetoothClassicService', () => { error: jest.fn(), warn: jest.fn() }; + const config: Partial = { + addresses: ['8d:ad:e3:e2:7a:01', 'f7:6c:e3:10:55:b5'] + }; + const configService = { + get: jest.fn().mockImplementation((key: string) => { + return key === 'bluetoothClassic' ? config : c.get(key); + }) + }; beforeEach(async () => { jest.clearAllMocks(); @@ -66,6 +77,8 @@ describe('BluetoothClassicService', () => { .useValue(entitiesService) .overrideProvider(ClusterService) .useValue(clusterService) + .overrideProvider(ConfigService) + .useValue(configService) .compile(); module.useLogger(loggerService); @@ -224,6 +237,45 @@ Requesting information ... expect(handleRssiMock).not.toHaveBeenCalled(); }); + it('should publish RSSI values that are bigger than the min RSSI', async () => { + jest.spyOn(service, 'shouldInquire').mockReturnValue(true); + jest.spyOn(service, 'inquireRssi').mockResolvedValue(-9); + const handleRssiMock = jest + .spyOn(service, 'handleNewRssi') + .mockImplementation(() => undefined); + config.minRssi = -10; + + await service.handleRssiRequest('77:50:fb:4d:ab:70'); + expect(handleRssiMock).toHaveBeenCalled(); + expect(clusterService.publish).toHaveBeenCalled(); + }); + + it('should publish RSSI values that are the same as the min RSSI', async () => { + jest.spyOn(service, 'shouldInquire').mockReturnValue(true); + jest.spyOn(service, 'inquireRssi').mockResolvedValue(-10); + const handleRssiMock = jest + .spyOn(service, 'handleNewRssi') + .mockImplementation(() => undefined); + config.minRssi = -10; + + await service.handleRssiRequest('77:50:fb:4d:ab:70'); + expect(handleRssiMock).toHaveBeenCalled(); + expect(clusterService.publish).toHaveBeenCalled(); + }); + + it('should not publish RSSI values that are smaller than the min RSSI', async () => { + jest.spyOn(service, 'shouldInquire').mockReturnValue(true); + jest.spyOn(service, 'inquireRssi').mockResolvedValue(-11); + const handleRssiMock = jest + .spyOn(service, 'handleNewRssi') + .mockImplementation(() => undefined); + config.minRssi = -10; + + await service.handleRssiRequest('77:50:fb:4d:ab:70'); + expect(handleRssiMock).not.toHaveBeenCalled(); + expect(clusterService.publish).not.toHaveBeenCalled(); + }); + it('should ignore RSSI requests of inquiries are disabled', () => { jest.spyOn(service, 'shouldInquire').mockReturnValue(false); const handleRssiMock = jest diff --git a/src/integrations/bluetooth-classic/bluetooth-classic.service.ts b/src/integrations/bluetooth-classic/bluetooth-classic.service.ts index cd9b2c8..fbc2ec9 100644 --- a/src/integrations/bluetooth-classic/bluetooth-classic.service.ts +++ b/src/integrations/bluetooth-classic/bluetooth-classic.service.ts @@ -87,7 +87,10 @@ export class BluetoothClassicService extends KalmanFilterable(Object, 1.4, 1) if (this.shouldInquire()) { let rssi = await this.inquireRssi(address); - if (rssi !== undefined) { + if ( + rssi !== undefined && + (!this.config.minRssi || rssi >= this.config.minRssi) + ) { rssi = _.round(this.filterRssi(address, rssi), 1); const event = new NewRssiEvent( this.configService.get('global').instanceName,