diff --git a/docs/integrations/bluetooth-classic.md b/docs/integrations/bluetooth-classic.md index 9aad6a53..42391e5a 100644 --- a/docs/integrations/bluetooth-classic.md +++ b/docs/integrations/bluetooth-classic.md @@ -53,15 +53,27 @@ Each configured device will create a sensor that has the name of the closest roo Each instance running this integration will also create a switch for enabling or disabling Bluetooth inquiries. A disabled switch blocks all Bluetooth requests of the instance, which essentially means that your Bluetooth device won't be discovered by this instance anymore. It does not take the instance out of the rotation however, so the time to detection stays the same. -You could use this to reduce the resources used by room-assistant when you are certain nobody is home. Another example would be disabling the inquiries when you are asleep to save the batteries of your Bluetooth devices at night. +You could use this to reduce the resources used by room-assistant when you are certain nobody is home. Another example would be disabling the inquiries when you are asleep to save the batteries of your Bluetooth devices at night. + +## Troubleshooting + +### Random incorrect not_home states + +This happens when no measurements were collected for the device recently. To make the timeout a bit more lax and get rid of these incorrect states you can raise the `timeoutCycles` value. Note that this will also delay your device being reported as `not_home` when it really has gone away. + +### WiFi/Bluetooth interference + +Bluetooth uses the 2.4 GHz band, which may also be used by some of your other WiFi devices. This can cause interferences. Some Bluetooth devices may also handle a too aggressive refresh interval badly. If you are noticing any issues (e.g. WiFi devices dropping off the network, Bluetooth headphones disconnecting randomly) try raising the `interval` a bit. Note that this will also make the state updates a bit slower. ## 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. | -| `hciDeviceId` | Number | 0 | ID of the Bluetooth device to use for the inquiries, e.g. `0` to use `hci0`. | +| 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. | +| `hciDeviceId` | Number | 0 | ID of the Bluetooth device to use for the inquiries, e.g. `0` to use `hci0`. | +| `interval` | Number | 6 | The interval at which the Bluetooth devices are queried in seconds. | +| `timeoutCycles` | Number | 2 | The number of completed query cycles after which collected measurements are considered obsolete. The timeout in seconds is calculated as `max(addresses, clusterDevices) * interval * timeoutCycles`. | ::: details Example Config ```yaml diff --git a/src/integrations/bluetooth-classic/bluetooth-classic.config.ts b/src/integrations/bluetooth-classic/bluetooth-classic.config.ts index 6d487d23..0f54e950 100644 --- a/src/integrations/bluetooth-classic/bluetooth-classic.config.ts +++ b/src/integrations/bluetooth-classic/bluetooth-classic.config.ts @@ -2,4 +2,6 @@ export class BluetoothClassicConfig { addresses: string[] = []; minRssi?: number; hciDeviceId = 0; + interval = 6; + timeoutCycles = 2; } diff --git a/src/integrations/bluetooth-classic/bluetooth-classic.service.spec.ts b/src/integrations/bluetooth-classic/bluetooth-classic.service.spec.ts index a4b4ebe3..c1521b5b 100644 --- a/src/integrations/bluetooth-classic/bluetooth-classic.service.spec.ts +++ b/src/integrations/bluetooth-classic/bluetooth-classic.service.spec.ts @@ -57,7 +57,9 @@ describe('BluetoothClassicService', () => { }; const config: Partial = { addresses: ['8d:ad:e3:e2:7a:01', 'f7:6c:e3:10:55:b5'], - hciDeviceId: 0 + hciDeviceId: 0, + interval: 6, + timeoutCycles: 2 }; const configService = { get: jest.fn().mockImplementation((key: string) => { diff --git a/src/integrations/bluetooth-classic/bluetooth-classic.service.ts b/src/integrations/bluetooth-classic/bluetooth-classic.service.ts index 945f1b55..f1481d9e 100644 --- a/src/integrations/bluetooth-classic/bluetooth-classic.service.ts +++ b/src/integrations/bluetooth-classic/bluetooth-classic.service.ts @@ -13,7 +13,7 @@ import { exec } from 'child_process'; import { Node } from 'democracy'; import { NewRssiEvent } from './new-rssi.event'; import _ from 'lodash'; -import { Interval, SchedulerRegistry } from '@nestjs/schedule'; +import { SchedulerRegistry } from '@nestjs/schedule'; import { EntityCustomization } from '../../entities/entity-customization.interface'; import { SensorConfig } from '../home-assistant/sensor-config'; import { @@ -28,7 +28,6 @@ import { DISTRIBUTED_DEVICE_ID } from '../home-assistant/home-assistant.const'; import { Switch } from '../../entities/switch'; import { SwitchConfig } from '../home-assistant/switch-config'; -const INTERVAL = 6 * 1000; const execPromise = util.promisify(exec); @Injectable() @@ -74,6 +73,15 @@ export class BluetoothClassicService extends KalmanFilterable(Object, 1.4, 1) ); this.clusterService.on(NEW_RSSI_CHANNEL, this.handleNewRssi.bind(this)); this.clusterService.subscribe(NEW_RSSI_CHANNEL); + + const interval = setInterval( + this.distributeInquiries.bind(this), + this.config.interval * 1000 + ); + this.schedulerRegistry.addInterval( + `bluetooth_classic_distribute_inquiries`, + interval + ); } /** @@ -140,7 +148,6 @@ 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(INTERVAL) distributeInquiries(): void { if (this.clusterService.isMajorityLeader()) { const nodes = this.getParticipatingNodes(); @@ -185,7 +192,7 @@ export class BluetoothClassicService extends KalmanFilterable(Object, 1.4, 1) const output = await execPromise( `hcitool -i hci${this.config.hciDeviceId} cc "${address}" && hcitool -i hci${this.config.hciDeviceId} rssi "${address}"`, { - timeout: 5.5 * 1000, + timeout: (this.config.interval - 0.5) * 1000, killSignal: 'SIGKILL' } ); @@ -343,7 +350,10 @@ export class BluetoothClassicService extends KalmanFilterable(Object, 1.4, 1) customizations ) as RoomPresenceDistanceSensor; - const interval = setInterval(sensor.updateState.bind(sensor), INTERVAL); + const interval = setInterval( + sensor.updateState.bind(sensor), + this.config.interval * 1000 + ); this.schedulerRegistry.addInterval(`${sensorId}_timeout_check`, interval); return sensor; @@ -357,7 +367,11 @@ export class BluetoothClassicService extends KalmanFilterable(Object, 1.4, 1) protected calculateCurrentTimeout(): number { const nodes = this.getParticipatingNodes(); const addresses = this.config.addresses; - return (Math.max(nodes.length, addresses.length) * 2 * INTERVAL) / 1000; + return ( + Math.max(nodes.length, addresses.length) * + this.config.timeoutCycles * + this.config.interval + ); } /**