|
11 | 11 |
|
12 | 12 | from bleak.backends.device import BLEDevice |
13 | 13 | from bleak.backends.scanner import AdvertisementData |
14 | | -from bleak_retry_connector import NO_RSSI_VALUE |
| 14 | +from bleak_retry_connector import NO_RSSI_VALUE, Allocations |
15 | 15 | from bluetooth_adapters import adapter_human_name |
16 | 16 | from bluetooth_data_tools import monotonic_time_coarse, parse_advertisement_data_bytes |
17 | 17 |
|
@@ -169,20 +169,51 @@ def _clear_connect_failure(self, address: str) -> None: |
169 | 169 | """Clear a connect failure.""" |
170 | 170 | self._connect_failures.pop(address, None) |
171 | 171 |
|
| 172 | + def get_allocations(self) -> Allocations | None: |
| 173 | + """ |
| 174 | + Get current connection slot allocations for this scanner. |
| 175 | +
|
| 176 | + Returns: |
| 177 | + Allocations object with free/limit/allocated info, or None if not available. |
| 178 | +
|
| 179 | + Note: |
| 180 | + Subclasses should override this method to provide their allocation info. |
| 181 | + For local adapters, this will be overridden in HaScanner to query |
| 182 | + BleakSlotManager. |
| 183 | + For remote scanners, they should override to return their own tracking. |
| 184 | +
|
| 185 | + """ |
| 186 | + return None |
| 187 | + |
172 | 188 | def _score_connection_paths( |
173 | 189 | self, rssi_diff: _int, scanner_device: BluetoothScannerDevice |
174 | 190 | ) -> float: |
175 | | - """Score the connection paths.""" |
| 191 | + """Score the connection paths considering slot availability.""" |
176 | 192 | address = scanner_device.ble_device.address |
177 | 193 | score = scanner_device.advertisement.rssi or NO_RSSI_VALUE |
178 | 194 | scanner_connections_in_progress = len(self._connect_in_progress) |
179 | 195 | previous_failures = self._connect_failures.get(address, 0) |
| 196 | + |
| 197 | + # Penalize scanners with connections in progress |
180 | 198 | if scanner_connections_in_progress: |
181 | 199 | # Very large penalty for multiple connections in progress |
182 | 200 | # to avoid overloading the adapter |
183 | 201 | score -= rssi_diff * scanner_connections_in_progress * 1.01 |
| 202 | + |
| 203 | + # Penalize based on previous failures |
184 | 204 | if previous_failures: |
185 | 205 | score -= rssi_diff * previous_failures * 0.51 |
| 206 | + |
| 207 | + # Consider connection slot availability |
| 208 | + allocation = self.get_allocations() |
| 209 | + if allocation and allocation.slots > 0: |
| 210 | + if allocation.free == 0: |
| 211 | + # No slots available - return NO_RSSI_VALUE to indicate unavailable |
| 212 | + return NO_RSSI_VALUE |
| 213 | + if allocation.free == 1: |
| 214 | + # Last slot available - small penalty to prefer adapters with more slots |
| 215 | + score -= rssi_diff * 0.76 |
| 216 | + |
186 | 217 | return score |
187 | 218 |
|
188 | 219 | def _connections_in_progress(self) -> int: |
|
0 commit comments